From dda36197902a3ac15c02e2e50090f95636e748ee Mon Sep 17 00:00:00 2001 From: nitescuc <1108077+nitescuc@users.noreply.github.com> Date: Thu, 25 Jun 2026 08:21:53 +0000 Subject: [PATCH] Update python SDK 1.132.2 --- crowdsec_service_api/__init__.py | 9 +- .../__pycache__/__init__.cpython-311.pyc | Bin 5024 -> 5171 bytes .../__pycache__/base_model.cpython-311.pyc | Bin 4378 -> 4378 bytes .../__pycache__/http_client.cpython-311.pyc | Bin 7768 -> 7768 bytes .../__pycache__/models.cpython-311.pyc | Bin 158635 -> 166507 bytes crowdsec_service_api/models.py | 408 +++++-- .../__pycache__/__init__.cpython-311.pyc | Bin 207 -> 207 bytes .../__pycache__/allowlists.cpython-311.pyc | Bin 12917 -> 12917 bytes .../__pycache__/blocklists.cpython-311.pyc | Bin 15121 -> 15121 bytes .../services/__pycache__/cves.cpython-311.pyc | Bin 12321 -> 12364 bytes .../__pycache__/decisions.cpython-311.pyc | Bin 4338 -> 7222 bytes .../__pycache__/fingerprints.cpython-311.pyc | Bin 12310 -> 12353 bytes .../services/__pycache__/hub.cpython-311.pyc | Bin 3277 -> 3277 bytes .../services/__pycache__/info.cpython-311.pyc | Bin 2035 -> 2035 bytes .../__pycache__/integrations.cpython-311.pyc | Bin 8075 -> 8075 bytes .../__pycache__/metrics.cpython-311.pyc | Bin 2607 -> 2607 bytes .../__pycache__/products.cpython-311.pyc | Bin 3782 -> 3782 bytes .../tracker_events.cpython-311.pyc | Bin 2914 -> 2914 bytes .../__pycache__/tracker_tags.cpython-311.pyc | Bin 5698 -> 5698 bytes .../__pycache__/vendors.cpython-311.pyc | Bin 10351 -> 10351 bytes crowdsec_service_api/services/allowlists.py | 2 +- crowdsec_service_api/services/blocklists.py | 2 +- crowdsec_service_api/services/cves.py | 3 +- crowdsec_service_api/services/decisions.py | 80 +- crowdsec_service_api/services/fingerprints.py | 3 +- crowdsec_service_api/services/hub.py | 2 +- crowdsec_service_api/services/info.py | 2 +- crowdsec_service_api/services/integrations.py | 2 +- crowdsec_service_api/services/metrics.py | 2 +- crowdsec_service_api/services/products.py | 2 +- .../services/tracker_events.py | 2 +- crowdsec_service_api/services/tracker_tags.py | 2 +- crowdsec_service_api/services/vendors.py | 2 +- doc/Blocklists.md | 8 +- doc/Cves.md | 6 +- doc/Decisions.md | 152 ++- doc/Fingerprints.md | 6 +- doc/Models.md | 104 +- doc/README.md | 16 +- public-openapi.json | 1079 ++++++++++++++--- pyproject.toml | 2 +- uv.lock | 20 +- 42 files changed, 1569 insertions(+), 347 deletions(-) diff --git a/crowdsec_service_api/__init__.py b/crowdsec_service_api/__init__.py index f2c57ce..d57f24c 100644 --- a/crowdsec_service_api/__init__.py +++ b/crowdsec_service_api/__init__.py @@ -33,6 +33,10 @@ class Server(Enum): 'TrackerTags', 'Fingerprints', 'TrackerEvents', + 'AggregatedDecisionItem', + 'AggregatedDecisionsGetResponse', + 'AggregatedDecisionsGetResponsePage', + 'AggregatedDecisionsSortBy', 'AllowlistCreateRequest', 'AllowlistCreateResponse', 'AllowlistGetItemsResponse', @@ -84,6 +88,8 @@ class Server(Enum): 'CtiScenario', 'DecisionCreateRequest', 'DecisionCreateResponse', + 'DecisionMachineState', + 'DecisionMachineStateEnum', 'DecisionResponse', 'DecisionTargetModel', 'DecisionTargetType', @@ -138,7 +144,7 @@ class Server(Enum): 'Behavior', 'CVEEventOutput', 'CVEExploitationPhase', - 'CVEResponseBase', + 'CVEResponseDetailed', 'CVEsubscription', 'CWE', 'Classification', @@ -149,7 +155,6 @@ class Server(Enum): 'FacetBucket', 'FingerprintEventOutput', 'FingerprintRuleResponse', - 'FingerprintRuleSummary', 'FingerprintTimelineItem', 'GetCVEIPsResponsePage', 'GetCVEProtectRulesResponse', diff --git a/crowdsec_service_api/__pycache__/__init__.cpython-311.pyc b/crowdsec_service_api/__pycache__/__init__.cpython-311.pyc index 2db00239d7de4999aa3c5ce54bc923355cb316a5..b66b8ee8265e9dbe54ecc08fbb708ac422ba611a 100644 GIT binary patch delta 249 zcmZ3WzFC8BIWI340}x0)waLmA-N?tm%(!i`IJ1jmdU{c6dSXdxic4y8W^rbIo@YsF z?kzb?@nZMXlAzS$g8aPV)LTjj`N^^zl2VcgKFplr;QXQzr^?L{%$+RyA}~?k#N>?3 zywudPHM{JgWT6Pujk2OWxTdoMktd} Ux}1rd=>r3TY+wh$A{n4x0n`6hdH?_b delta 124 zcmdn2u|S<~IWI340|=CAW$h8!$j8CVxN)*Lv&-g7%xx^2J2);d3-CLKxdx>c7v$#^ zr#dATr%uk{xh5{=mYJ8HT2xS!nO722nv)t_nwy(gRJqxaH)C- diff --git a/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc b/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc index 1bc5815900c09dcc5d59b8b7d1636dda5e5ee5f9..3caeeeb11e40ea9f5b8ddc926efe6daa328b3e47 100644 GIT binary patch delta 20 acmca%bHj#vIWI340}wDjwb{t+D+d5SAO%VQ delta 20 acmca%bHj#vIWI340}wnd(b~xED+d5VP6ep| diff --git a/crowdsec_service_api/__pycache__/models.cpython-311.pyc b/crowdsec_service_api/__pycache__/models.cpython-311.pyc index 6ec2ace3e093ffc22a4a8f92ab2f5aa7fa9fef13..3966b3dbc949fc7dc8758e94d15ae0eba88f601f 100644 GIT binary patch delta 37805 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 b_jaoHvWT{40qm-4SABSyc3ShsROf#IJ*tZ8 delta 32894 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 r=-x7~gM@1UYiPS -# timestamp: 2026-06-11T08:42:40+00:00 +# timestamp: 2026-06-25T08:21:45+00:00 from __future__ import annotations @@ -13,6 +13,27 @@ from .base_model import BaseModelSdk, RootModelSdk +class Total(RootModelSdk[int]): + root: Annotated[int, Field(ge=0, title='Total')] + + +class Page(RootModelSdk[int]): + root: Annotated[int, Field(ge=1, title='Page')] + + +class Size(RootModelSdk[int]): + root: Annotated[int, Field(ge=1, title='Size')] + + +class Pages(RootModelSdk[int]): + root: Annotated[int, Field(ge=0, title='Pages')] + + +class AggregatedDecisionsSortBy(StrEnum): + FIRST_CREATED_AT = 'first_created_at' + FIRST_EXPIRATION = 'first_expiration' + + class AllowlistCreateRequest(BaseModelSdk): model_config = ConfigDict( extra='forbid', @@ -76,22 +97,6 @@ class AllowlistCreateResponse(BaseModelSdk): ] -class Total(RootModelSdk[int]): - root: Annotated[int, Field(ge=0, title='Total')] - - -class Page(RootModelSdk[int]): - root: Annotated[int, Field(ge=1, title='Page')] - - -class Size(RootModelSdk[int]): - root: Annotated[int, Field(ge=1, title='Size')] - - -class Pages(RootModelSdk[int]): - root: Annotated[int, Field(ge=0, title='Pages')] - - class AllowlistItemUpdateRequest(BaseModelSdk): model_config = ConfigDict( extra='forbid', @@ -420,6 +425,12 @@ class DecisionCreateResponse(BaseModelSdk): ] +class DecisionMachineStateEnum(StrEnum): + PENDING_CREATE = 'PENDING_CREATE' + PENDING_DELETE = 'PENDING_DELETE' + APPLIED = 'APPLIED' + + class DecisionTargetType(StrEnum): ORG = 'org' TAG = 'tag' @@ -1380,7 +1391,7 @@ class BlocklistsUploadBlocklistContentQueryParameters(BaseModelSdk): Optional[datetime], Field( description='Blocklist expiration', - examples=['2026-06-11T08:40:13.370581+00:00'], + examples=['2026-06-25T08:19:41.526068+00:00'], title='Expiration', ), ] = None @@ -1587,6 +1598,12 @@ class IntegrationsGetIntegrationContentStreamPathParameters(BaseModelSdk): class DecisionsGetDecisionsQueryParameters(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 instance_ids: Annotated[ Optional[List[str]], Field( @@ -1619,6 +1636,30 @@ class DecisionsGetDecisionsQueryParameters(BaseModelSdk): title='Ips', ), ] = [] + alert_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by associated alert IDs', + examples=[['alert-abc123', 'alert-def456']], + title='Alert Ids', + ), + ] = [] + decision_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by decision IDs', + examples=[['dec-abc123', 'dec-def456']], + title='Decision Ids', + ), + ] = [] + created_at_from: Annotated[ + Optional[datetime], + Field( + description='Filter decisions created after this date (inclusive)', + examples=['2023-01-01T00:00:00Z'], + title='Created At From', + ), + ] = None sort_by: Annotated[ Optional[DecisionsSortBy], Field( @@ -1635,15 +1676,99 @@ class DecisionsGetDecisionsQueryParameters(BaseModelSdk): title='Sort Order', ), ] = 'desc' + + +class DecisionsDeleteDecisionPathParameters(BaseModelSdk): + decision_id: Annotated[str, Field(title='Decision Id')] + + +class DecisionsGetAggregatedDecisionsQueryParameters(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 + instance_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by instance IDs', + examples=[['inst-abc123', 'inst-def456']], + title='Instance Ids', + ), + ] = [] + tag_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by tag IDs', + examples=[['tag-001', 'tag-002']], + title='Tag Ids', + ), + ] = [] + remediation_types: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by remediation types', + examples=[['ban', 'captcha']], + title='Remediation Types', + ), + ] = [] + ips: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by IPs (only for IP decisions)', + examples=[['203.0.113.7', '198.51.100.42']], + title='Ips', + ), + ] = [] + alert_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by associated alert IDs', + examples=[['alert-abc123', 'alert-def456']], + title='Alert Ids', + ), + ] = [] + decision_ids: Annotated[ + Optional[List[str]], + Field( + description='Filter decisions by decision IDs', + examples=[['dec-abc123', 'dec-def456']], + title='Decision Ids', + ), + ] = [] + created_at_from: Annotated[ + Optional[datetime], + Field( + description='Filter decisions created after this date (inclusive)', + examples=['2023-01-01T00:00:00Z'], + title='Created At From', + ), + ] = None + sort_by: Annotated[ + Optional[AggregatedDecisionsSortBy], + Field( + description='Field to sort by (e.g., created_at, duration)', + examples=['created_at'], + title='Sort By', + ), + ] = 'first_created_at' + sort_order: Annotated[ + Optional[DecisionsSortOrder], + Field( + description="Sort order: 'asc' for ascending, 'desc' for descending", + examples=['desc'], + title='Sort Order', + ), + ] = 'desc' -class DecisionsDeleteDecisionPathParameters(BaseModelSdk): +class DecisionsDeleteAggregatedDecisionsPathParameters(BaseModelSdk): + aggregated_id: Annotated[str, Field(title='Aggregated Id')] + + +class DecisionsDeleteAggregatedDecisionItemPathParameters(BaseModelSdk): + aggregated_id: Annotated[str, Field(title='Aggregated Id')] decision_id: Annotated[str, Field(title='Decision Id')] @@ -1749,6 +1874,14 @@ class CvesGetCvesQueryParameters(BaseModelSdk): title='Exploitation Phase', ), ] = None + detailed: Annotated[ + Optional[bool], + Field( + description='Include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE in the list. Defaults to false to keep the response lightweight.', + examples=[True], + title='Detailed', + ), + ] = False page: Annotated[ Optional[int], Field(description='Page number', ge=1, title='Page') ] = 1 @@ -2177,6 +2310,14 @@ class FingerprintsGetFingerprintRulesQueryParameters(BaseModelSdk): title='Sort Order', ), ] = 'desc' + detailed: Annotated[ + Optional[bool], + Field( + description='Include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each fingerprint rule in the list. Defaults to false to keep the response lightweight.', + examples=[True], + title='Detailed', + ), + ] = False page: Annotated[ Optional[int], Field(description='Page number', ge=1, title='Page') ] = 1 @@ -2647,6 +2788,16 @@ class BlocklistSubscriptionRequest(BaseModelSdk): ] = None +class DecisionMachineState(BaseModelSdk): + timestamp: Annotated[ + datetime, + Field(description='Date of when the state has been set', title='Timestamp'), + ] + state: Annotated[ + DecisionMachineStateEnum, Field(description='State of the decision') + ] + + class DecisionTargetModel(BaseModelSdk): type: Annotated[ DecisionTargetType, Field(description='Type of the decision target') @@ -3728,7 +3879,7 @@ class ScenarioIndex(BaseModelSdk): ] = None -class CVEResponseBase(BaseModelSdk): +class CVEResponseDetailed(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')] @@ -3808,6 +3959,29 @@ class CVEResponseBase(BaseModelSdk): 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[ + Optional[List[str]], + Field(description='List of references for the CVE', title='References'), + ] = None + description: Annotated[ + Optional[str], Field(description='Description of the CVE', title='Description') + ] = None + crowdsec_analysis: Annotated[ + Optional[str], + Field(description='CrowdSec analysis of the CVE', title='Crowdsec Analysis'), + ] = None + cwes: Annotated[ + Optional[List[CWE]], + Field(description='List of CWEs associated with the CVE', title='Cwes'), + ] = None + events: Annotated[ + Optional[List[CVEEventOutput]], + Field(description='List of events related to the CVE', title='Events'), + ] = None class FingerprintRuleResponse(BaseModelSdk): @@ -3892,61 +4066,6 @@ class FingerprintRuleResponse(BaseModelSdk): ] = 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')] @@ -4062,7 +4181,7 @@ class GetCVESubscribedIntegrationsResponsePage(BaseModelSdk): class GetCVEsResponsePage(BaseModelSdk): - items: Annotated[List[CVEResponseBase], Field(title='Items')] + items: Annotated[List[CVEResponseDetailed], 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')] @@ -4071,7 +4190,7 @@ class GetCVEsResponsePage(BaseModelSdk): class GetFingerprintRulesResponsePage(BaseModelSdk): - items: Annotated[List[FingerprintRuleSummary], Field(title='Items')] + items: Annotated[List[FingerprintRuleResponse], 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')] @@ -4398,6 +4517,141 @@ class ProtectRule(BaseModelSdk): ] = None +class AggregatedDecisionItem(BaseModelSdk): + id: Annotated[ + str, Field(description='ID of the decision aggregated item', title='Id') + ] + first_created_at: Annotated[ + datetime, + Field( + description='Creation date of the first decision in the group', + title='First Created At', + ), + ] + last_created_at: Annotated[ + datetime, + Field( + description='Creation date of the last decision in the group', + title='Last Created At', + ), + ] + origin: Annotated[str, Field(description='Origin of the decision', title='Origin')] + scenario: Annotated[ + str, Field(description='Scenario of the decision', title='Scenario') + ] + min_duration: Annotated[ + str, + Field( + description='Min duration in the group of decisions', title='Min Duration' + ), + ] + max_duration: Annotated[ + str, + Field( + description='Max durations in the group of decisions', title='Max Duration' + ), + ] + first_expiration: Annotated[ + datetime, + Field( + description='First expiration date in the group of decisions', + title='First Expiration', + ), + ] + last_expiration: Annotated[ + datetime, + Field( + description='Last expiration date in the group of decisions', + title='Last Expiration', + ), + ] + count: Annotated[ + int, Field(description='Number of decisions in the group', title='Count') + ] + machines: Annotated[ + Dict[str, DecisionMachineState], + Field( + description='Machines object (the instance ID is the key) with the decision status and timestamp', + title='Machines', + ), + ] + target: Annotated[DecisionTargetModel, Field(description='Target of the decision')] + + +class AggregatedDecisionsGetResponse(BaseModelSdk): + id: Annotated[ + str, Field(description='ID of the decision aggregated item', title='Id') + ] + 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 + first_created_at: Annotated[ + Optional[datetime], + Field( + description='Creation date of the first decision in the group', + title='First Created At', + ), + ] = None + last_created_at: Annotated[ + Optional[datetime], + Field( + description='Creation date of the last decision in the group', + title='Last Created At', + ), + ] = None + first_expiration: Annotated[ + Optional[datetime], + Field( + description='Expiration date of the first decision in the group', + title='First Expiration', + ), + ] = None + last_expiration: Annotated[ + Optional[datetime], + Field( + description='Expiration date of the last decision in the group', + title='Last Expiration', + ), + ] = None + decisions: Annotated[ + List[AggregatedDecisionItem], + Field(description='List of decisions in the group', title='Decisions'), + ] + + +class AggregatedDecisionsGetResponsePage(BaseModelSdk): + items: Annotated[List[AggregatedDecisionsGetResponse], Field(title='Items')] + total: Annotated[Optional[Total], Field(title='Total')] = None + page: Annotated[Optional[Page], Field(title='Page')] = None + size: Annotated[Optional[Size], Field(title='Size')] = None + pages: Annotated[Optional[Pages], Field(title='Pages')] = None + links: Links + + class AllowlistGetItemsResponse(BaseModelSdk): id: Annotated[ str, diff --git a/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/__init__.cpython-311.pyc index 03cc6cd2b678c4bb7fde146020819a3126108035..c18720a373dd314ce03ed712d60a0ef61ed5fdbf 100644 GIT binary patch delta 19 ZcmX@lc%G4aIWI340}wDjwVB9$1OPD81p5F0 delta 19 ZcmX@lc%G4aIWI340}wnd(VED81OPLl1zG?A diff --git a/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc index 43c12d0fa29acc733d3ff5413d13fc4bbf224419..ecf28a48a3d620ede72f8f789b78b0bf81113bfa 100644 GIT binary patch delta 30 kcmeyG@->BfIWI340}x0)wb{s>z|3N7q-V4_pP5Y`0FUBfIWI340|=CAZRAd1W-+qRGuWKZ%%%?jhFb@1 diff --git a/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc index d87cdb1bac7f4880ebeb44a85f3d6e4d5ffdd4cb..cdc7b86e2fa1d416ca5410f374c8ffe4add9b52c 100644 GIT binary patch delta 30 kcmbPOHnEI*IWI340}x0)wb{u1fSJYENY7~VduAnb0EK@Dg#Z8m delta 30 jcmbPOHnEI*IWI340|=CAZRCEy%wlArXR!G_vywRgd*cV~ diff --git a/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc index 7d05d919d947b7bbc0e723946bb4f0ca957ad427..3c5aabc9005171552f2799e38fed845c3a0c8c1d 100644 GIT binary patch delta 2165 zcma)8Uuaup6u)13^SAdVO`5-L(xy$?{OOvywz0O|A6Sd6XdPP%Zoze{{l1KpGzqua zST(hXgY`kn=A4U*Y5MRayDf%GDnCIMB(#-zZ4f*B! zoqN9XJLi1oUb1%Krwj7uvTPFI^89gRZfsp1CCyf(aQ*o!5rk{P4S@*>LWP8ecJMSA zU#9g*J(ZY&iJpohAeDjZc5pLr{SIycZrs5en2B0hJ+;ACWKyz$HeS^xWNK$3aC1_m zj;mtA@*i&i?gVZHzKjkc7+hem83p{%PSw%#R8m!e#-xchfq)%+L%aHl%#qa5X7F*U z5yPriHG(T?pkBD^?x#NH!JCjm3#8DbI<~6Z54;&9BC1VhUfKpJ`B)3z)VPlOSZlQd z5Uw4<`Bl#VYlEVEtbNCQ9SuUXz>08%B!ZJdB+8$!`%&!cjrA7mL z+Ip}{T=oWf3v;U2wPZ^{}hB zssDj^qv(4Gp%)-xQ2KD)j}YhI8(a9JfKj6i@(0G|*5ha$MmT~{tEC*}UrSCtWO9;d z@s#P|0in-I(e2QylAnyg=5cbY__uWDfQ`SHJ8`3|3_=biG0(2#72NIQK}(pNE>2j+ zG;P(Y4r8WjX~vq;Zd)T{fZw-C04sWokwNFR49H+=T#S!Pqvy}AE9oG#&%B2|Ja{Kw1$Fi;Wx+fk{ z^`5D$?>y7w!=k5YNOLp+;ieR|o9AH}(JI~86P&Hel&LeIPK(-OeNB(Adk^DL4a4)2 zUC2jFN)ztGK#H2pUWJ$RxtYauc80=CX?;~N@e88#@(1lH@(-U1#BIAgBOe7Km9Dq* zj{|o8Tfj0@nJCcQE?G??fJw|9kVz;wN`5b-NvtitC)F=FSpLjAiXdOs9`Db$BMn-y zkc388Syq>3!D1_0)MW!MD=Id@=q)#*)m~Ao!TzH0(42a{vGU delta 2187 zcma)6TWlLe6rFL_Z*SIi>^M&RO6=I)Je+5n<|#;`rYJmAT8glsB+8Ddi<7u(rwY_j zS`mpL@t%*C9}pjRPn*wafoiqp77;uN9Zzr_f>j4mUBl2}1Wof4)Qd~7{sP^`p6 z1n+JfLW+%XLlqYpH&*d_#?4h+A{NEYZh=@+^@?LdpR_4XA}}td1f^j^NY?LiiE$U> z_FXQd)&<4Q91b&rpAz8|u@byI(9d~*@n$9w<31Z{QG%=_AMsbZu2`&39|=@A69_SZAm7_c zLVUfoYTcl;vHWeDXcZ^*;S)%X)3Lg*h5jRnUd=4HF%9ZRMIk%?94QL9^owM{NYCm0 z*hu@VEqYTLt(oa1(Y;?|%pqC9A7U`@pOmjw;zlQ~=34m?}MUzT$+2y4i$%%~8tHvSh z)V??VfPFH=bOQ7-kWFeo*aHBA^p-hbJq+d$z!8cqEx`#eM*v0vYK7D>I%?^{vUbMu z%K^EwwvL+IS8X9YNx!lk!{eGHUO!;>&-Ky9s>)a;MIldC^XepRmnOvH%#nMA!9`Ru z(M$fI_J-uswN{$#h1z+?=9-ST9I^rO7Tf5y!$l>hL?y{gW6ofLH~t9hivq*|_L)Q8 zIfIGzh4b}l+4~hiE6%mn-R`nMHz-bc?K^3Y)82)?K#8#i^)16u{* z9y;L-(YV)+57S}qAaC`&w_oOh|EtSw?`iyw*4sRy8-I#rJgIWs)6A6hY8QL(^H)BJ z{HXAg#m8W*8T>V0-}JvPv?yekb9vdKHbVx;rt*^ZYQJdA&cBdZo>$oU+x9lmLH`3- z(^mYV?%wlVEBbEm(0E1EppXp76WLsr<%$Yu?qvUQb23@K4%Hk=Lp! zn2M_zwpGSO+sX7I$)uOaLwT~OE-`0L#~>6^eUSScy%bB}2Kq^C(0PBM^v_s~)fb3I zp}ww~!K}dceFx*AZ^q;JZ~9sM*XY9#9Rg@&AY&CAvaZ_os2rhNa(1#Vy_8pnA#@zz zL4YZMqX07ivjE2d9tSuD@Fc*~0MF2kj)-9a%ro@kj?Ta$n0W?8+llnj0(mT(PqS~K zx(faa^skNq`~>anJiqR8-*PpUB#(X?mk{7>$#bRd)wPnIy9~(Le5HHG5ic1zHzBwG zroVf~l_;6H!-D+nH`|AId?O_*ci52REQ#E#2eX{oj?BK2gL}D3S*wH$+|{oQcAeGX z0s3Czg3Q0W@Xc2p0Pu=bKLEVFJEpP4Wo0EpCe*j+RL}L<839kS%J+V34*gbM{bQdX GF7OX*Z?ZH1 diff --git a/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc index d705642e1226909db262b964ed97acbc6e614089..cdd55a6b8309129e001619cb6075a134612b96f1 100644 GIT binary patch literal 7222 zcmeHMO>7&-6`m!R4k4nk45c5R?WPi|45X;Gj(6|^8g!~zBk6h+}n!N3Vn_|*4i zfA}Lxahe_qw4>phc{6Y4=k532ydC{K7z_|deSe$0@NtxozanENk5zf_6R3PbRH6zw zlETuJ6Y{Q&VL~IUh^~ zIWOfp^PyCT*ZsM!d^i>6&j)gmd^8mmh>M&iYR4s_$~17*O~?)SnJE=hg&C3v-bZ#i zAsEthu|Q{+N;Kg%q?by1wpd8#4A092s2Kheg+ftJ>r}n(0(lS@MiVYWJe!`UhHr+l zx3U=u4gQm9jlNh^DLnanmgZED^z+J@!dwv;@x-FO0A*lG*Gs2zSz6FD=7LPxXE6^B zz&!7P)+k8{DoMH2J*tbkRW}t;KXcwyGAF3sOTm;!^{LW4ssE`S7olF&e^r3}!p}_5 z=2HXBZF3!J2bDlKk{YCbD%z71qIS0Mp%%WYg%7vzkrqBm15M+{fcG}c*A2X{ffs4V zTwLwB;p?=}3-(o9wZplT2IE&#B!CzHvvn$H%-)1~Zq zh85pdHJTYOP(At9VM9y<1`X*AfU2^{a)y^teUTNWGmdcpWYBn#e{dGa$HFH>cc4Vb zRcN~bKQpa0^w@2LlwD;(6>hqk%??c!mh7Hh92#X^Cyr1Ex={V16Mg%xvj3@2`^!%UQ+u`8MiQkMFf)@iL-ORBc!$4g5L zU+Qwic^TvO8iUZTC4l_%BDpIC-}ims+mzz#QhaUXR;+UJhZQM)M@nx<>582nfH1j_ zioJgXh!Myz%2$-u4N;|9#t=*Bdqgd}Obt0((DZa6LzS$m89qHd&nsa@^Hj~I(U&PY zxHipjXG@ylPvOUl8Y2_Fh;`2Mye)pgU|Y~jt^N(koZDw7NL z2}IVsTLyuKvRv*ehsvEd#j7yS4QH;EupX+*t6tSpCRw2zZV&WkW587dzNrj)k0+9%F6K)Lf4T#mgf+O~o~ODI zcOHg;&Qq-fra|#^yB=ZvpbNGS$qRyZKynbt2oeN18%1&m$zwoZ*9Emy%ocR+ zY22^}_HFEZ0?7nQNX(i|ivSC@+LG7+N(Et&ij7rmxz}0lcvD9g$Z9_Ya*@;qNPKuz zzS|jlf8m3LRd+QKTlL)ycVF(mD?eV5k3zmRVV0Zn>2>*Zb#QOZO@dRx=foB4`~u16 zZZQ)0f&f|d)&iurZ?)rIw09#qv>83P9z9s?8n|}o_S~Q6;knodJQf3CAgj`s66qSL zgr*?h5`o;7ei!^r@YkW=hRnu_G{pvSUp_|PT%?+waSQ=k9itL$qjK$FRBiyf2tN<} zysE40ehc15dm}3gYYoN+Gg(P>g9*S~^>Cq?D?kXc;sb+nOk~Y5Eqe?s!RLF+p0Zf> z-Sk`qi5rg8iln0xv=TRP>1&x28;57vb3kTU5@^E1&@plhnP}p;I*x5evERpzVVyTT ziM2^2-vt7$v#9AtkBy;I+_l=EPxwv1<5cVfl9NbUQ0ptDm(T>+Dd^PvKpfbbfVEty zgW2UidpZpcWc1}u7w$~^6%YWe)CRQGaCFsM?TN2;)MV1xdu6B+9EAL(pG12vk5=XA zraZJR4_WvfZh~(V;TsLqIFZQkNX<|DU4Z3SoWpozJv!pRxbk`ik(_8n@_|a|802fx zFN41bUJu;_5F=laj+r3tuniLqk@i6T3+#@c4vz%n_TX(gApq=U_cu5pypM1?SYY0A zI{0`9cLQd<;K4yIA(`m> z9uB=7I!#bYAYy~k!lXHd1H48|wsdh={}@IvF?pobk#bDl?diXK;jVnRA|Hc%>y%k; z%2Vs|l!eAK&EB*Z;n*ACNVX6-x*i>M5Qy+Q)CfN?h_2YGZsM$KF3U7ssRt?l4@KY& zHKc7qk>&0Npr+^N8J)*ivJs`}hi8kt(WlzDN#=bU> zw8R+f84%p@_>bc$UthU{U~PGyvko2!w3B%iN3RD3$yO{|LBW$1`2^(KGiJFdpIevD zSuj4|4C8-4C^%9HoripT7|3TMe;WJ4*zc2nOqz`q>AZ>aV8br{w>;|pwm?n3+oX_3 zaIcR$s4(5@iLJ2R&eO7KfQ#*BUxxbEcC))IU)r!})&5Fct~>tm9mEz9vUT_SbSq>V z-S1>Y2G4uywq}-_^31wCW8rqT8Moia{We_>I3cQYvb%Q(QJwJg5l?pU8=UMIraEEg zHs5{jvJV5*EhoEVpX|pU35Ut7PV?H=J^ClU5}RjW*qz~N#i$&fj}Qv9iBETLk3I#r zwVZI4xdTwS==%uP_kcjG5FqgxVJEacU6G%M{MnFMZpyE$%dc2yef2+x)`Y^x=peXPqyqLqftSE0TrgLTw>jY85t?7(k;TR!j?=x`!adOG1-|1k(OLz?e zS1AR!i^*l-Df}#APa}C22kN#Tx4$g-Cmx$Zfftaxgi?KNoRT>mn?a#jB;QB!8j1(4 zORWse<>1y!V7s7IgO4`y43F+u7)6ob{fzc^_@IQ_Ci}1E50G0Vzp zidp#z8X(<0)mTq;-*9zsclBVR+PAB^doQwyvFh05HRbl}cg9}W7<-{Q@myu%xzFbA zOuV=;@nWrSz;gzsMtZL^T=Q_&OG1&Fk5?tqyX(rt zxj#K#3v#xTbVfcJ`rrq(5NEsKL*|P6^6^@jvk`l!C}(4&f8W~Br-QX_&i0T<|CQuM zc(m5b`8eqwtPCbMVvk#E>?i)cwOzcAFV|eOMJJ=4j8kY@-T+MHN>1CpN-Qpbnv-S%=U7Iy{6rgevH;g-)V&di&dIXC!L%K?!^7 z=|la34!@G{pot?t(apd24G+KUWO&zMc%hyx%$qif2Lto+W_~B883BF`&KZVolHvce z45_rFrVDyD!#c1HEy@VlZR2zJpB;_ig@)n5tF(8x1L2no3~vriTf}P!b8UEq^-!8L zozGLO04y4=_75O6w;%{r(s7ahRY`xPIakS8W&3=O^i=FzB?l_)a+U0_w98xDtM*V0 dV-8nHQ?7|;T>`w8_Vgp)=e*~OZTh)B{ssMPu3-QG delta 1118 zcmZ`%OK1~87@kS@o$RLBY_>_$XiE@Xt8MC|ty&+orByunIM{$l$V|#gZ0jU~k4Ob&SrI>VbrC zt-Q+bx4MG?y(t&yitJc{G*_C&fmHLa;IdAyTREuHM^;ugd~hvF3r=2Ee9$oHhr~WP z#ypcQD)|AuVK!oo=nLto#9kYlt#Qq&$A57Ekb>j}@L|Jx4CxmoN$>E{mbYW0hx zK`wXkb(QSqTo^-~?cuPOzBarqJcjJ&aDcZsoIrKtZ^Q>)6vsC$FF6@W0*ICf{wBzBGH`AsU!e_aL!ZgJ;tx?$n4> z^=oy)-*3?7&(z5X&pO0qY8;pSnm;=;CO+~BeBmNyrQ^I{g2OR7-LW%r9@52*lhOR9 zW^QA1v)9aIsh-ZxH=R_|al>RrJ_WkOX*4Rm!sZd=?F z>Ova8vKR7qroyO@F<^H-=wD834Najfkjj0?^)EYxFfNRC5VymGpf;z;yx+~1poj5 diff --git a/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc index 43a3794d6559f7bed7b0eeec2036e4ad35245093..80aacea5dd06f96846e855f39abaedf456d75965 100644 GIT binary patch delta 2250 zcma)6Uu;ul6#u^Vw!OXWZP%`U)@>c#pLVXw)FdmjDkwm>4CfiIM7y4@O=z@qqv#ku=fBgKyK6;2Y6+&R1Dmn8VxLU(Y$; z`Of)$=bZapI(*}>dR0{w0#D?((c_a}suQ%qiz+-1Z&E_uB9{pxGgK!t7QKz9>Ex2` znzie0CNn8gas<>>(Crnv2Xse;?qyEBhAFxaUWvJ8J-YwAZN{zFG6{5PR?-9Kr5V*p z@TbRxJ@iD5(*7k3;F(qQFa+>|b7ECziPZqjI`Hv{knO^&Ou;`Z>k(M3)$3UR*MLF; zPzVaYMxjSR4?%_wVQXSxeI1jRSY5@rBo<-yWgUXXAZWwNCY3en&2WwgimL_&$hfK)4xXnvc_)0vh%MAHgfv)+;h2YLtce_7*{PVyF8`$k!3xnwHM z^n#R49%BW`Or2pz9V`7I1Z69{4;AR@WuntX2frmZ*yI#hbn>zGR+~LV7G(aNYl}?* zn~P@~TKgOet_5Ym`MLCoM963GmYzj-?(vj>LAUF+1(Ko*ZvLRXi=VdtLRCKPXc{uw zVYT39b9y$Dn#&zJX`~C*bmpkh2X>g@@?9vp-&gW zdH_u}22dVE*uZ~xZsO;H&H-Z>^n#RQ^SNuXQICtyA&ekwL8#7WjPh5N{Zz|;t?aWj zms9kktH|T5%HxU0_={@9z6sU~1AIJK&v&Q_zo2^UL%3y_f24Nyij>Yd7(6Jiw1J-KAg)SMOd5aiY< z%EiVoU-s>$)A=#~B}?L&g~5blK%}2{1#9RgJ{p{Gm8taemx68li(o(#mHA&qSq{FT zz7Ao{`vB)i(amot0e;Bu$iEY+w`_d{ta}Z?Yd?sZ&FF?dF+-(k5`7laAu8#pYUBO7 zaTph6M9OB&oTiitgK^fLmVzUjJe|%Ybr_rFU>$!mGELvj{}gGkJUN}!={$|wG2NhD zXK9vWRh>A9S=a2uDf)3obUmUUei^#-=O7qb# z=Ho(4<~L*Bk(H)AKDFpb5=k6+1`|ASU-R?yn|!wU!wNPNl<@;?k?=9tZ(0CiF{2S< z9S1nGh2M5WxjUio>umwL%ztQGm98hgx$>jxi7QjPlDXG*C5_|>D4Agzt21xKL~{sh z)DW59iBHhG`EVlf)JIlTH;7c|78RTCsKqNKR=QHclc~95%*YyWdF?)#X1o8rri>Th z0txXSJBH~W+^T(*m_RNugk}JZ8fefgm8P9qEB{%W*&rRsWZ)Krh{k5zuoYn&!W6;| zgq;X4BkV=k$605${Q!!G`Q=W{K8xZB{(Wb>2EP^~hj0pEo86v^s%ap-|q`SU;4jVMI>2SO;(^Z)<= delta 2134 zcma)6S!`QX5WUxaeqLX^#9O>Hc4Iq!S)5H-nvJGSqgERnhky?v`hhG_RpOIHM)U*m#hvRmc1jX>);pe= zJ2PkI&e-=Ct}RHnB*}!}S#CQO`$C$;eu=9H{rNRU=py<65tPIVN@|q7G>fO!(mKUV z3`A&p;)jr8VY*nSOH9|-=?%oFSlKHOQ`(}~F6feG#ZCmK3u!@dTo95LBZ808!tKsy z^4H>}^qNU=u>=jwIkK&@K&)v|aWfwqPZ{N2wG{TWLGiFthvFrTaK=h#VkJ1apO5Q) zrn?wJjN1altpr&~9%yN;+BU1*OPXpuvZQ-hQr~8fh4__b7UU&?npaKY@xhwT;zKNc z4<{5zGb<|0iU?goXK^w-i{#d_Wh%3DlF)wbH$v}FqPwIOqL|9MR!PXGPLi@v$ebgK zB7NQLq~~=;EYhnUzeb;-Hj9s5X|!QIz1cXTGiK1LiRO$gUE+#q#kgYlT=-N#=ri_K zpH*|w`c!7K6&2kI%HS0#DO@twgGfAkPT`N$h`o4R4@&U^n*A6 zFvy@R6v^4*ZG-9q%NW2ufMI~G-0BEjHXXbrJtq(;39;ji`#ezA1iajl+khhC}VI#eYaXJkIw;d0YUE-NRz>DniA!vEFg zM$}9F?pJWWbk04Y8Jl4Z98-D2b4-+VYCGH$tU`4u_=xy)`CaJiCqV!5PE2l&yDa2$ zg`#Y#P8zc9KJKzUpL#Q!ODSybP}TcQC-CLc?@fNqvpcqxG#WTGRwES^k|jkV8|xPA zCE(uW=5Gbg;7>};!8wgs9X0KY929P2wVU2=Ud0>qxlq4{x4UJ#S=Mq7zy6;>26`t1 zOSc{x7~b6Vr@ixOEI<*d|EL7|o(k{BUzIL~Kd!50vO{5!GA`SXEGe1AR57O>E*A4M zsp6|@nw=Ch3_>9_0QocY!^nR83w;>bscQI{_~}~INT;LKpUThTU1Cee`I1Va@6K(dn*8Zru#7Aizgf&vorPs}&tLiOAu*-ub{DujsjMK(65T!OjQH zM8(JrCS-L~%v`j9Sk2UcjPZ(L=Lk&;=j4ycHe$E*i)s)62L88U^mI;H&XRHUU3#EveWIYn!xgkWUK#v@pFG~-oTvQ<>YJ~; diff --git a/crowdsec_service_api/services/__pycache__/hub.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/hub.cpython-311.pyc index 9c5bafe5e48a74bcc5b7523b7ea994a416066e27..afcd82e2a1a58e2d1a079a9de09cd0ec6b173bf7 100644 GIT binary patch delta 30 kcmX>rc~+8pIWI340}x0)wb{sB&BS7Cq-V6bi^-V_0C;u>YXATM delta 30 jcmX>rc~+8pIWI340|=CAZRDmdrX#lIWI340}x0)wb{u1h>6A6NY7~VN2aUX0Dn~o#sB~S delta 30 jcmX>mdrX#lIWI340|=CAZRCE$#A0NjXR!Gr(^YN&b-4&G diff --git a/crowdsec_service_api/services/__pycache__/tracker_events.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/tracker_events.cpython-311.pyc index 80c82367ed26d1b3aa8f4a8bc76f0c16126bf6b6..cd91dac961231f3ae8c36c1b3a1fffd41197bad4 100644 GIT binary patch delta 30 kcmaDP_DGC-IWI340}x0)wb{sho{7cSNY7~VJ*E~80D@2mb^rhX delta 30 jcmaDP_DGC-IWI340|=CAZR9@B#A0NjXR!GmQws+Gc(e!J diff --git a/crowdsec_service_api/services/__pycache__/tracker_tags.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/tracker_tags.cpython-311.pyc index 7aeca28cde4a0ff40e041360eb356d7d52e08cab..1502151434bd9e88a43c6c9f48342a4291cc6473 100644 GIT binary patch delta 30 kcmX@4b4Z7KIWI340}x0)wb{sB&dg$Lq-V6bjd_m{0D9;L_5c6? delta 30 jcmX@4b4Z7KIWI340|=CAZR9RzW-+qRGuYh5yhjKCaZCqZ diff --git a/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc index d4f743a50282e1bb623c56cac65a0e44cf40b373..889e9dc1c0f0f4e7a8fdc830c495f40702a9ae8b 100644 GIT binary patch delta 30 kcmaDK@IHWhIWI340}x0)wb{shl9|QWNY7~V4d&@80FmMeDF6Tf delta 30 jcmaDK@IHWhIWI340|=CAZR9@5%wlArXR!GO^K=yeh(-vJ diff --git a/crowdsec_service_api/services/allowlists.py b/crowdsec_service_api/services/allowlists.py index 057a909..473a8b3 100644 --- a/crowdsec_service_api/services/allowlists.py +++ b/crowdsec_service_api/services/allowlists.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def list_allowlists( self, diff --git a/crowdsec_service_api/services/blocklists.py b/crowdsec_service_api/services/blocklists.py index ac2cad5..37965d3 100644 --- a/crowdsec_service_api/services/blocklists.py +++ b/crowdsec_service_api/services/blocklists.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_blocklists( self, diff --git a/crowdsec_service_api/services/cves.py b/crowdsec_service_api/services/cves.py index 6d90155..0bb4bcf 100644 --- a/crowdsec_service_api/services/cves.py +++ b/crowdsec_service_api/services/cves.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_cves( self, @@ -19,6 +19,7 @@ def get_cves( sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), exploitation_phase: Optional[CVEExploitationPhase] = None, + detailed: bool = False, page: int = 1, size: int = 50, )-> GetCVEsResponsePage: diff --git a/crowdsec_service_api/services/decisions.py b/crowdsec_service_api/services/decisions.py index 7468e0a..91ac113 100644 --- a/crowdsec_service_api/services/decisions.py +++ b/crowdsec_service_api/services/decisions.py @@ -11,18 +11,21 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_decisions( self, + page: int = 1, + size: int = 50, instance_ids: list[str] = [], tag_ids: list[str] = [], remediation_types: list[str] = [], ips: list[str] = [], + alert_ids: list[str] = [], + decision_ids: list[str] = [], + created_at_from: Optional[str] = None, 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() @@ -80,4 +83,75 @@ def delete_decision( ) return None + + def get_aggregated_decisions( + self, + page: int = 1, + size: int = 50, + instance_ids: list[str] = [], + tag_ids: list[str] = [], + remediation_types: list[str] = [], + ips: list[str] = [], + alert_ids: list[str] = [], + decision_ids: list[str] = [], + created_at_from: Optional[str] = None, + sort_by: Optional[AggregatedDecisionsSortBy] = AggregatedDecisionsSortBy("first_created_at"), + sort_order: Optional[DecisionsSortOrder] = DecisionsSortOrder("desc"), + )-> AggregatedDecisionsGetResponsePage: + endpoint_url = "/decisions/aggregated" + loc = locals() + headers = {} + params = json.loads( + DecisionsGetAggregatedDecisionsQueryParameters(**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 AggregatedDecisionsGetResponsePage(_client=self, **response.json()) + + def delete_aggregated_decisions( + self, + aggregated_id: str, + ): + endpoint_url = "/decisions/aggregated/{aggregated_id}" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + DecisionsDeleteAggregatedDecisionsPathParameters(**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 delete_aggregated_decision_item( + self, + aggregated_id: str, + decision_id: str, + ): + endpoint_url = "/decisions/aggregated/{aggregated_id}/items/{decision_id}" + loc = locals() + headers = {} + params = {} + path_params = json.loads( + DecisionsDeleteAggregatedDecisionItemPathParameters(**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 \ No newline at end of file diff --git a/crowdsec_service_api/services/fingerprints.py b/crowdsec_service_api/services/fingerprints.py index 1bc0b40..90719c8 100644 --- a/crowdsec_service_api/services/fingerprints.py +++ b/crowdsec_service_api/services/fingerprints.py @@ -11,13 +11,14 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_fingerprint_rules( self, query: Optional[str] = None, sort_by: Optional[GetCVEsSortBy] = GetCVEsSortBy("rule_release_date"), sort_order: Optional[GetCVEsSortOrder] = GetCVEsSortOrder("desc"), + detailed: bool = False, page: int = 1, size: int = 50, )-> GetFingerprintRulesResponsePage: diff --git a/crowdsec_service_api/services/hub.py b/crowdsec_service_api/services/hub.py index 3a1546e..8f37c03 100644 --- a/crowdsec_service_api/services/hub.py +++ b/crowdsec_service_api/services/hub.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_index( self, diff --git a/crowdsec_service_api/services/info.py b/crowdsec_service_api/services/info.py index c5b2050..0e7d693 100644 --- a/crowdsec_service_api/services/info.py +++ b/crowdsec_service_api/services/info.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_info( self, diff --git a/crowdsec_service_api/services/integrations.py b/crowdsec_service_api/services/integrations.py index 73f5656..e2178f1 100644 --- a/crowdsec_service_api/services/integrations.py +++ b/crowdsec_service_api/services/integrations.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_integrations( self, diff --git a/crowdsec_service_api/services/metrics.py b/crowdsec_service_api/services/metrics.py index 322c7c5..f0ab224 100644 --- a/crowdsec_service_api/services/metrics.py +++ b/crowdsec_service_api/services/metrics.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_metrics_remediation( self, diff --git a/crowdsec_service_api/services/products.py b/crowdsec_service_api/services/products.py index 5d173fc..186dd1c 100644 --- a/crowdsec_service_api/services/products.py +++ b/crowdsec_service_api/services/products.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_products( self, diff --git a/crowdsec_service_api/services/tracker_events.py b/crowdsec_service_api/services/tracker_events.py index fa41f55..e3b12bc 100644 --- a/crowdsec_service_api/services/tracker_events.py +++ b/crowdsec_service_api/services/tracker_events.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_exploitation_phase_change_events( self, diff --git a/crowdsec_service_api/services/tracker_tags.py b/crowdsec_service_api/services/tracker_tags.py index 270d8f4..d77c059 100644 --- a/crowdsec_service_api/services/tracker_tags.py +++ b/crowdsec_service_api/services/tracker_tags.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_tags( self, diff --git a/crowdsec_service_api/services/vendors.py b/crowdsec_service_api/services/vendors.py index dab3932..58291da 100644 --- a/crowdsec_service_api/services/vendors.py +++ b/crowdsec_service_api/services/vendors.py @@ -11,7 +11,7 @@ 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/1.128.0") + super().__init__(base_url=base_url, auth=auth, user_agent="crowdsec_service_api/1.132.2") def get_vendors( self, diff --git a/doc/Blocklists.md b/doc/Blocklists.md index 78168f1..fd190ed 100644 --- a/doc/Blocklists.md +++ b/doc/Blocklists.md @@ -80,7 +80,7 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 409 | Blocklist already exists | +| 409 | Already exists | | 422 | Validation Error | ### Usage @@ -178,7 +178,7 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 404 | Blocklist not found | +| 404 | Not found | | 422 | Validation Error | ### Usage @@ -251,8 +251,8 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 403 | Blocklist is read-only | -| 404 | Blocklist not found | +| 403 | Read-only | +| 404 | Not found | | 500 | Internal server error | | 422 | Validation Error | ### Usage diff --git a/doc/Cves.md b/doc/Cves.md index 9b8a39b..a0e497f 100644 --- a/doc/Cves.md +++ b/doc/Cves.md @@ -3,7 +3,7 @@ # Cves Methods | Method | Description | | ------ | ----------- | -| [get_cves](#get_cves) | Get a paginated list of CVEs that CrowdSec is tracking | +| [get_cves](#get_cves) | Get a paginated list of CVEs that CrowdSec is tracking. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE; they are omitted by default to keep the list light. | | [get_cve](#get_cve) | Get information about 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 | @@ -16,7 +16,7 @@ | [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 +### Get a paginated list of CVEs that CrowdSec is tracking. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE; they are omitted by default to keep the list light. - Endpoint: `/cves` - Method: `GET` @@ -27,6 +27,7 @@ | 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 | +| detailed | bool | Include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE in the list. Defaults to false to keep the response lightweight. | False | False | | page | int | Page number | False | 1 | | size | int | Page size | False | 50 | ### Returns: @@ -51,6 +52,7 @@ try: sort_by=rule_release_date, sort_order=desc, exploitation_phase=None, + detailed=True, page=1, size=50, ) diff --git a/doc/Decisions.md b/doc/Decisions.md index d4b739b..1a9c134 100644 --- a/doc/Decisions.md +++ b/doc/Decisions.md @@ -6,6 +6,9 @@ | [get_decisions](#get_decisions) | Get decisions | | [create_decision](#create_decision) | Create a new decision. | | [delete_decision](#delete_decision) | Delete a decision by its UUID. | +| [get_aggregated_decisions](#get_aggregated_decisions) | None | +| [delete_aggregated_decisions](#delete_aggregated_decisions) | Delete one decision by ID | +| [delete_aggregated_decision_item](#delete_aggregated_decision_item) | Delete one decision by ID | ## **get_decisions** ### Get decisions @@ -15,21 +18,23 @@ ### Parameters: | Parameter | Type | Description | Required | Default | | --------- | ---- | ----------- | -------- | ------- | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | | 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 | [] | +| alert_ids | list[str] | Filter decisions by associated alert IDs | False | [] | +| decision_ids | list[str] | Filter decisions by decision IDs | False | [] | +| created_at_from | Optional[str] | Filter decisions created after this date (inclusive) | False | None | | 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 @@ -43,14 +48,17 @@ auth = ApiKeyAuth(api_key='your_api_key') client = Decisions(auth=auth) try: response = client.get_decisions( + page=1, + size=50, instance_ids=['sample-item'], tag_ids=['sample-item'], remediation_types=['sample-item'], ips=['sample-item'], + alert_ids=['sample-item'], + decision_ids=['sample-item'], + created_at_from=None, sort_by=created_at, sort_order=desc, - page=1, - size=50, ) print(response) except HTTPStatusError as e: @@ -72,7 +80,7 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 409 | Conflict: Decision value is in allowlists; cannot create decision. | +| 409 | Already exists | | 422 | Validation Error | ### Usage @@ -125,7 +133,9 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 422 | Validation Error | +| 422 | Unprocessable entity | +| 404 | Not found | +| 500 | Internal server error | ### Usage ```python @@ -145,3 +155,131 @@ except HTTPStatusError as e: print(f"An error occurred: {e.response.status_code} - {e.response.text}") ``` + +## **get_aggregated_decisions** +### None +- Endpoint: `/decisions/aggregated` +- Method: `GET` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| page | int | Page number | False | 1 | +| size | int | Page size | False | 50 | +| 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 | [] | +| alert_ids | list[str] | Filter decisions by associated alert IDs | False | [] | +| decision_ids | list[str] | Filter decisions by decision IDs | False | [] | +| created_at_from | Optional[str] | Filter decisions created after this date (inclusive) | False | None | +| sort_by | Optional[AggregatedDecisionsSortBy] | Field to sort by (e.g., created_at, duration) | False | AggregatedDecisionsSortBy("first_created_at") | +| sort_order | Optional[DecisionsSortOrder] | Sort order: 'asc' for ascending, 'desc' for descending | False | DecisionsSortOrder("desc") | +### Returns: +[AggregatedDecisionsGetResponsePage](./Models.md#aggregateddecisionsgetresponsepage) +### Errors: +| Code | Description | +| ---- | ----------- | +| 404 | Not found | +| 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_aggregated_decisions( + page=1, + size=50, + instance_ids=['sample-item'], + tag_ids=['sample-item'], + remediation_types=['sample-item'], + ips=['sample-item'], + alert_ids=['sample-item'], + decision_ids=['sample-item'], + created_at_from=None, + sort_by=first_created_at, + sort_order=desc, + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **delete_aggregated_decisions** +### Delete one decision by ID +- Endpoint: `/decisions/aggregated/{aggregated_id}` +- Method: `DELETE` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| aggregated_id | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Unprocessable entity | +| 404 | Not found | +| 500 | Internal server 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.delete_aggregated_decisions( + aggregated_id='aggregated_id', + ) + print(response) +except HTTPStatusError as e: + print(f"An error occurred: {e.response.status_code} - {e.response.text}") +``` + + +## **delete_aggregated_decision_item** +### Delete one decision by ID +- Endpoint: `/decisions/aggregated/{aggregated_id}/items/{decision_id}` +- Method: `DELETE` + +### Parameters: +| Parameter | Type | Description | Required | Default | +| --------- | ---- | ----------- | -------- | ------- | +| aggregated_id | str | | True | | +| decision_id | str | | True | | +### Errors: +| Code | Description | +| ---- | ----------- | +| 422 | Unprocessable entity | +| 404 | Not found | +| 500 | Internal server 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.delete_aggregated_decision_item( + aggregated_id='aggregated_id', + decision_id='decision_id', + ) + 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 index addb9a3..c804f4b 100644 --- a/doc/Fingerprints.md +++ b/doc/Fingerprints.md @@ -3,7 +3,7 @@ # Fingerprints Methods | Method | Description | | ------ | ----------- | -| [get_fingerprint_rules](#get_fingerprint_rules) | Get a paginated list of fingerprint rules | +| [get_fingerprint_rules](#get_fingerprint_rules) | Get a paginated list of fingerprint rules. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each rule; they are omitted by default to keep the list light. | | [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 | @@ -15,7 +15,7 @@ | [get_fingerprint_rule](#get_fingerprint_rule) | Get information about a specific fingerprint rule | ## **get_fingerprint_rules** -### Get a paginated list of fingerprint rules +### Get a paginated list of fingerprint rules. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each rule; they are omitted by default to keep the list light. - Endpoint: `/fingerprints` - Method: `GET` @@ -25,6 +25,7 @@ | 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") | +| detailed | bool | Include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each fingerprint rule in the list. Defaults to false to keep the response lightweight. | False | False | | page | int | Page number | False | 1 | | size | int | Page size | False | 50 | ### Returns: @@ -48,6 +49,7 @@ try: query=None, sort_by=rule_release_date, sort_order=desc, + detailed=True, page=1, size=50, ) diff --git a/doc/Models.md b/doc/Models.md index b6ab9c0..1b552a0 100644 --- a/doc/Models.md +++ b/doc/Models.md @@ -1,5 +1,63 @@ +# **AggregatedDecisionItem** +## Required: +id, first_created_at, last_created_at, origin, scenario, min_duration, max_duration, first_expiration, last_expiration, count, machines, target +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | ID of the decision aggregated item || +| first_created_at | str | Creation date of the first decision in the group || +| last_created_at | str | Creation date of the last decision in the group || +| origin | str | Origin of the decision || +| scenario | str | Scenario of the decision || +| min_duration | str | Min duration in the group of decisions || +| max_duration | str | Max durations in the group of decisions || +| first_expiration | str | First expiration date in the group of decisions || +| last_expiration | str | Last expiration date in the group of decisions || +| count | int | Number of decisions in the group || +| machines | Machines | Machines object (the instance ID is the key) with the decision status and timestamp || +| target | DecisionTargetModel | None || + +# **AggregatedDecisionsGetResponse** +## Required: +id, scope, type, value, decisions +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| id | str | ID of the decision aggregated item || +| 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 || +| first_created_at | str | Creation date of the first decision in the group || +| last_created_at | str | Creation date of the last decision in the group || +| first_expiration | str | Expiration date of the first decision in the group || +| last_expiration | str | Expiration date of the last decision in the group || +| decisions | list[AggregatedDecisionItem] | List of decisions in the group || + +# **AggregatedDecisionsGetResponsePage** +## Required: +items, page, size, links +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| items | list[AggregatedDecisionsGetResponse] | None || +| total | Optional[int] | None || +| page | Optional[int] | None || +| size | Optional[int] | None || +| pages | Optional[int] | None || +| links | Links | None || + +# **AggregatedDecisionsSortBy** +## Enum: +FIRST_CREATED_AT, FIRST_EXPIRATION + # **AllowlistCreateRequest** ## Required: name @@ -553,6 +611,19 @@ uuid |----------|------|-------------|---------| | uuid | str | UUID of the created decision || +# **DecisionMachineState** +## Required: +timestamp, state +## Properties +| Property | Type | Description | Example | +|----------|------|-------------|---------| +| timestamp | str | Date of when the state has been set || +| state | DecisionMachineStateEnum | None || + +# **DecisionMachineStateEnum** +## Enum: +PENDING_CREATE, PENDING_DELETE, APPLIED + # **DecisionResponse** ## Required: uuid, id, duration, origin, scenario, scope, type, value, target @@ -1107,7 +1178,7 @@ name, date, description, label, sorting_priority ## Enum: INSUFFICIENT_DATA, EARLY_EXPLOITATION, FRESH_AND_POPULAR, TARGETED_EXPLOITATION, MASS_EXPLOITATION, BACKGROUND_NOISE, UNPOPULAR, WEARING_OUT, UNCLASSIFIED -# **CVEResponseBase** +# **CVEResponseDetailed** ## Required: id, name, title, affected_components, crowdsec_score, nb_ips, published_date, has_public_exploit, exploitation_phase ## Properties @@ -1130,6 +1201,12 @@ id, name, title, affected_components, crowdsec_score, nb_ips, published_date, ha | 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 | Optional[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 || # **CVEsubscription** ## Required: @@ -1249,27 +1326,6 @@ id, name, title, affected_components, crowdsec_score, nb_ips, exploitation_phase | 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 @@ -1347,7 +1403,7 @@ items, total, page, size, pages, links ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| items | list[CVEResponseBase] | None || +| items | list[CVEResponseDetailed] | None || | total | int | None || | page | int | None || | size | int | None || @@ -1381,7 +1437,7 @@ items, total, page, size, pages, links ## Properties | Property | Type | Description | Example | |----------|------|-------------|---------| -| items | list[FingerprintRuleSummary] | None || +| items | list[FingerprintRuleResponse] | None || | total | int | None || | page | int | None || | size | int | None || diff --git a/doc/README.md b/doc/README.md index 445188f..0ce498f 100644 --- a/doc/README.md +++ b/doc/README.md @@ -39,6 +39,14 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ ## API Endpoint models +[AggregatedDecisionItem](./Models.md#aggregateddecisionitem) + +[AggregatedDecisionsGetResponse](./Models.md#aggregateddecisionsgetresponse) + +[AggregatedDecisionsGetResponsePage](./Models.md#aggregateddecisionsgetresponsepage) + +[AggregatedDecisionsSortBy](./Models.md#aggregateddecisionssortby) + [AllowlistCreateRequest](./Models.md#allowlistcreaterequest) [AllowlistCreateResponse](./Models.md#allowlistcreateresponse) @@ -141,6 +149,10 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [DecisionCreateResponse](./Models.md#decisioncreateresponse) +[DecisionMachineState](./Models.md#decisionmachinestate) + +[DecisionMachineStateEnum](./Models.md#decisionmachinestateenum) + [DecisionResponse](./Models.md#decisionresponse) [DecisionTargetModel](./Models.md#decisiontargetmodel) @@ -249,7 +261,7 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [CVEExploitationPhase](./Models.md#cveexploitationphase) -[CVEResponseBase](./Models.md#cveresponsebase) +[CVEResponseDetailed](./Models.md#cveresponsedetailed) [CVEsubscription](./Models.md#cvesubscription) @@ -271,8 +283,6 @@ You can find a Quickstart about this SDK, following this [documentation](https:/ [FingerprintRuleResponse](./Models.md#fingerprintruleresponse) -[FingerprintRuleSummary](./Models.md#fingerprintrulesummary) - [FingerprintTimelineItem](./Models.md#fingerprinttimelineitem) [GetCVEIPsResponsePage](./Models.md#getcveipsresponsepage) diff --git a/public-openapi.json b/public-openapi.json index 2e5d94e..612cf94 100644 --- a/public-openapi.json +++ b/public-openapi.json @@ -3,7 +3,7 @@ "info": { "title": "Service API", "description": "This is the API to manage Crowdsec services", - "version": "1.70.29", + "version": "1.70.40", "contact": { "name": "CrowdSec", "url": "https://crowdsec.net", @@ -820,7 +820,7 @@ } }, "409": { - "description": "Blocklist already exists" + "description": "Already exists" }, "422": { "description": "Validation Error", @@ -1097,7 +1097,7 @@ } }, "404": { - "description": "Blocklist not found" + "description": "Not found" }, "422": { "description": "Validation Error", @@ -1155,10 +1155,10 @@ } }, "403": { - "description": "Blocklist is read-only" + "description": "Read-only" }, "404": { - "description": "Blocklist not found" + "description": "Not found" }, "500": { "description": "Internal server error" @@ -1270,7 +1270,7 @@ ], "description": "Blocklist expiration", "examples": [ - "2026-06-11T08:40:13.370581+00:00" + "2026-06-25T08:19:41.526068+00:00" ], "title": "Expiration" }, @@ -2445,6 +2445,33 @@ "description": "Get decisions", "operationId": "getDecisions", "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" + }, { "name": "instance_ids", "in": "query", @@ -2529,6 +2556,70 @@ }, "description": "Filter decisions by IPs (only for IP decisions)" }, + { + "name": "alert_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by associated alert IDs", + "examples": [ + [ + "alert-abc123", + "alert-def456" + ] + ], + "default": [], + "title": "Alert Ids" + }, + "description": "Filter decisions by associated alert IDs" + }, + { + "name": "decision_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by decision IDs", + "examples": [ + [ + "dec-abc123", + "dec-def456" + ] + ], + "default": [], + "title": "Decision Ids" + }, + "description": "Filter decisions by decision IDs" + }, + { + "name": "created_at_from", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter decisions created after this date (inclusive)", + "examples": [ + "2023-01-01T00:00:00Z" + ], + "title": "Created At From" + }, + "description": "Filter decisions created after this date (inclusive)" + }, { "name": "sort_by", "in": "query", @@ -2572,33 +2663,6 @@ "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": { @@ -2615,9 +2679,6 @@ "404": { "description": "Not found" }, - "500": { - "description": "Internal server error" - }, "422": { "description": "Validation Error", "content": { @@ -2659,7 +2720,7 @@ } }, "409": { - "description": "Conflict: Decision value is in allowlists; cannot create decision." + "description": "Already exists" }, "422": { "description": "Validation Error", @@ -2695,17 +2756,350 @@ ], "responses": { "204": { - "description": "Successful Response" + "description": "No Content" + }, + "422": { + "description": "Unprocessable entity" + }, + "404": { + "description": "Not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/decisions/aggregated": { + "get": { + "tags": [ + "Decisions" + ], + "summary": "Get Aggregated Decisions", + "operationId": "getAggregatedDecisions", + "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" + }, + { + "name": "instance_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by instance IDs", + "examples": [ + [ + "inst-abc123", + "inst-def456" + ] + ], + "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", + "examples": [ + [ + "tag-001", + "tag-002" + ] + ], + "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", + "examples": [ + [ + "ban", + "captcha" + ] + ], + "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)", + "examples": [ + [ + "203.0.113.7", + "198.51.100.42" + ] + ], + "default": [], + "title": "Ips" + }, + "description": "Filter decisions by IPs (only for IP decisions)" + }, + { + "name": "alert_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by associated alert IDs", + "examples": [ + [ + "alert-abc123", + "alert-def456" + ] + ], + "default": [], + "title": "Alert Ids" + }, + "description": "Filter decisions by associated alert IDs" + }, + { + "name": "decision_ids", + "in": "query", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter decisions by decision IDs", + "examples": [ + [ + "dec-abc123", + "dec-def456" + ] + ], + "default": [], + "title": "Decision Ids" + }, + "description": "Filter decisions by decision IDs" + }, + { + "name": "created_at_from", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Filter decisions created after this date (inclusive)", + "examples": [ + "2023-01-01T00:00:00Z" + ], + "title": "Created At From" + }, + "description": "Filter decisions created after this date (inclusive)" + }, + { + "name": "sort_by", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/AggregatedDecisionsSortBy" + }, + { + "type": "null" + } + ], + "description": "Field to sort by (e.g., created_at, duration)", + "examples": [ + "created_at" + ], + "default": "first_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", + "examples": [ + "desc" + ], + "default": "desc", + "title": "Sort Order" + }, + "description": "Sort order: 'asc' for ascending, 'desc' for descending" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AggregatedDecisionsGetResponsePage" + } + } + } + }, + "404": { + "description": "Not found" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/decisions/aggregated/{aggregated_id}": { + "delete": { + "tags": [ + "Decisions" + ], + "summary": "Delete Aggregated Decision", + "description": "Delete one decision by ID", + "operationId": "deleteAggregatedDecisions", + "parameters": [ + { + "name": "aggregated_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Aggregated Id" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "422": { + "description": "Unprocessable entity" + }, + "404": { + "description": "Not found" + }, + "500": { + "description": "Internal server error" + } + } + } + }, + "/decisions/aggregated/{aggregated_id}/items/{decision_id}": { + "delete": { + "tags": [ + "Decisions" + ], + "summary": "Delete Aggregated Decision Item", + "description": "Delete one decision by ID", + "operationId": "deleteAggregatedDecisionItem", + "parameters": [ + { + "name": "aggregated_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Aggregated Id" + } + }, + { + "name": "decision_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Decision Id" + } + } + ], + "responses": { + "204": { + "description": "No Content" }, "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "description": "Unprocessable entity" + }, + "404": { + "description": "Not found" + }, + "500": { + "description": "Internal server error" } } } @@ -3110,7 +3504,7 @@ "Cves" ], "summary": "Get list of CVEs CrowdSec is tracking", - "description": "Get a paginated list of CVEs that CrowdSec is tracking", + "description": "Get a paginated list of CVEs that CrowdSec is tracking. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE; they are omitted by default to keep the list light.", "operationId": "getCves", "parameters": [ { @@ -3199,6 +3593,21 @@ }, "description": "Filter by exploitation phase" }, + { + "name": "detailed", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE in the list. Defaults to false to keep the response lightweight.", + "examples": [ + true + ], + "default": false, + "title": "Detailed" + }, + "description": "Include the heavy detail fields (description, crowdsec_analysis, cwes, references, events, tags) for each CVE in the list. Defaults to false to keep the response lightweight." + }, { "name": "page", "in": "query", @@ -5139,7 +5548,7 @@ "Fingerprints" ], "summary": "Get list of fingerprint rules", - "description": "Get a paginated list of fingerprint rules", + "description": "Get a paginated list of fingerprint rules. Pass detailed=true to also include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each rule; they are omitted by default to keep the list light.", "operationId": "getFingerprintRules", "parameters": [ { @@ -5207,6 +5616,21 @@ }, "description": "Sort order: ascending or descending" }, + { + "name": "detailed", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each fingerprint rule in the list. Defaults to false to keep the response lightweight.", + "examples": [ + true + ], + "default": false, + "title": "Detailed" + }, + "description": "Include the heavy detail fields (description, crowdsec_analysis, references, events, tags) for each fingerprint rule in the list. Defaults to false to keep the response lightweight." + }, { "name": "page", "in": "query", @@ -5988,24 +6412,326 @@ "$ref": "#/components/schemas/ExploitationPhaseChangeEventsResponsePage" } } - } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AggregatedDecisionItem": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the decision aggregated item" + }, + "first_created_at": { + "type": "string", + "format": "date-time", + "title": "First Created At", + "description": "Creation date of the first decision in the group" + }, + "last_created_at": { + "type": "string", + "format": "date-time", + "title": "Last Created At", + "description": "Creation date of the last decision in the group" + }, + "origin": { + "type": "string", + "title": "Origin", + "description": "Origin of the decision" + }, + "scenario": { + "type": "string", + "title": "Scenario", + "description": "Scenario of the decision" + }, + "min_duration": { + "type": "string", + "title": "Min Duration", + "description": "Min duration in the group of decisions" + }, + "max_duration": { + "type": "string", + "title": "Max Duration", + "description": "Max durations in the group of decisions" + }, + "first_expiration": { + "type": "string", + "format": "date-time", + "title": "First Expiration", + "description": "First expiration date in the group of decisions" + }, + "last_expiration": { + "type": "string", + "format": "date-time", + "title": "Last Expiration", + "description": "Last expiration date in the group of decisions" + }, + "count": { + "type": "integer", + "title": "Count", + "description": "Number of decisions in the group" + }, + "machines": { + "additionalProperties": { + "$ref": "#/components/schemas/DecisionMachineState" + }, + "type": "object", + "title": "Machines", + "description": "Machines object (the instance ID is the key) with the decision status and timestamp" + }, + "target": { + "$ref": "#/components/schemas/DecisionTargetModel", + "description": "Target of the decision" + } + }, + "type": "object", + "required": [ + "id", + "first_created_at", + "last_created_at", + "origin", + "scenario", + "min_duration", + "max_duration", + "first_expiration", + "last_expiration", + "count", + "machines", + "target" + ], + "title": "AggregatedDecisionItem" + }, + "AggregatedDecisionsGetResponse": { + "properties": { + "id": { + "type": "string", + "title": "Id", + "description": "ID of the decision aggregated item" + }, + "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" + }, + "first_created_at": { + "type": "string", + "format": "date-time", + "title": "First Created At", + "description": "Creation date of the first decision in the group" + }, + "last_created_at": { + "type": "string", + "format": "date-time", + "title": "Last Created At", + "description": "Creation date of the last decision in the group" + }, + "first_expiration": { + "type": "string", + "format": "date-time", + "title": "First Expiration", + "description": "Expiration date of the first decision in the group" + }, + "last_expiration": { + "type": "string", + "format": "date-time", + "title": "Last Expiration", + "description": "Expiration date of the last decision in the group" + }, + "decisions": { + "items": { + "$ref": "#/components/schemas/AggregatedDecisionItem" + }, + "type": "array", + "title": "Decisions", + "description": "List of decisions in the group" + } + }, + "type": "object", + "required": [ + "id", + "scope", + "type", + "value", + "decisions" + ], + "title": "AggregatedDecisionsGetResponse" + }, + "AggregatedDecisionsGetResponsePage": { + "properties": { + "items": { + "items": { + "$ref": "#/components/schemas/AggregatedDecisionsGetResponse" + }, + "type": "array", + "title": "Items" + }, + "total": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" + } + ], + "title": "Total" + }, + "page": { + "anyOf": [ + { + "type": "integer", + "minimum": 1.0 + }, + { + "type": "null" + } + ], + "title": "Page" + }, + "size": { + "anyOf": [ + { + "type": "integer", + "minimum": 1.0 + }, + { + "type": "null" + } + ], + "title": "Size" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } + "pages": { + "anyOf": [ + { + "type": "integer", + "minimum": 0.0 + }, + { + "type": "null" } - } + ], + "title": "Pages" + }, + "links": { + "$ref": "#/components/schemas/Links", + "readOnly": true } - } - } - } - }, - "components": { - "schemas": { + }, + "type": "object", + "required": [ + "items", + "page", + "size", + "links" + ], + "title": "AggregatedDecisionsGetResponsePage" + }, + "AggregatedDecisionsSortBy": { + "type": "string", + "enum": [ + "first_created_at", + "first_expiration" + ], + "title": "AggregatedDecisionsSortBy" + }, "AllowlistCreateRequest": { "properties": { "name": { @@ -8247,6 +8973,35 @@ ], "title": "DecisionCreateResponse" }, + "DecisionMachineState": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "Date of when the state has been set" + }, + "state": { + "$ref": "#/components/schemas/DecisionMachineStateEnum", + "description": "State of the decision" + } + }, + "type": "object", + "required": [ + "timestamp", + "state" + ], + "title": "DecisionMachineState" + }, + "DecisionMachineStateEnum": { + "type": "string", + "enum": [ + "PENDING_CREATE", + "PENDING_DELETE", + "APPLIED" + ], + "title": "DecisionMachineStateEnum" + }, "DecisionResponse": { "properties": { "created_at": { @@ -11278,7 +12033,7 @@ ], "title": "CVEExploitationPhase" }, - "CVEResponseBase": { + "CVEResponseDetailed": { "properties": { "id": { "type": "string", @@ -11421,6 +12176,62 @@ } ], "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": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "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", @@ -11435,8 +12246,8 @@ "has_public_exploit", "exploitation_phase" ], - "title": "CVEResponseBase", - "description": "GET CVE ID Response" + "title": "CVEResponseDetailed", + "description": "List item able to carry the heavy detail fields.\n\nThe list endpoint only populates these when ``detailed=true`` is passed;\notherwise they are left unset and stripped from the response via\n``response_model_exclude_unset``. All fields are therefore optional so a\nlean list item stays valid. Values are served straight from the cache\n(same source as the detail endpoint)." }, "CVEsubscription": { "properties": { @@ -11876,138 +12687,6 @@ ], "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": { @@ -12350,7 +13029,7 @@ "properties": { "items": { "items": { - "$ref": "#/components/schemas/CVEResponseBase" + "$ref": "#/components/schemas/CVEResponseDetailed" }, "type": "array", "title": "Items" @@ -12459,7 +13138,7 @@ "properties": { "items": { "items": { - "$ref": "#/components/schemas/FingerprintRuleSummary" + "$ref": "#/components/schemas/FingerprintRuleResponse" }, "type": "array", "title": "Items" diff --git a/pyproject.toml b/pyproject.toml index 3475644..3bb3d98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "crowdsec_service_api" -version = "1.128.0" +version = "1.132.2" license = { text = "MIT" } authors = [ { name="crowdsec", email="info@crowdsec.net" } diff --git a/uv.lock b/uv.lock index 2dd3cda..af1cf75 100644 --- a/uv.lock +++ b/uv.lock @@ -13,43 +13,43 @@ wheels = [ [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.1" 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" } +sdist = { url = "https://files.pythonhosted.org/packages/3b/72/5562aabb8dd7181e8e860622a38bea08d17842b99ecd4c91f84ac95251b0/anyio-4.14.1.tar.gz", hash = "sha256:8d648a3544c1a700e3ff78615cd679e4c5c3f149904287e73687b2596963629e", size = 254831, upload-time = "2026-06-24T20:56:06.017Z" } 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" }, + { url = "https://files.pythonhosted.org/packages/b0/7b/90df4a0a816d98d6ea26f559d87836d494a2cf1fcf063be67df50a7bcc30/anyio-4.14.1-py3-none-any.whl", hash = "sha256:4e5533c5b8ff0a24f5d7a176cbe6877129cd183893f66b537f8f227d10527d72", size = 124875, upload-time = "2026-06-24T20:56:04.413Z" }, ] [[package]] name = "botocore" -version = "1.43.27" +version = "1.43.36" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fa/4e/db50ef135f1d9ffc85e209a124004a5829d8f12f4a7a0afdf380cb19866d/botocore-1.43.27.tar.gz", hash = "sha256:2093c316c24214e50e18640b1869513b759bb8cc48b95b004a8306cb9f0d6703", size = 15504242, upload-time = "2026-06-10T19:38:25.389Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/37/da9e7f6ca73ac73afd7f0bb7f238aa5daba35c081e98d7f48a7c399599c0/botocore-1.43.36.tar.gz", hash = "sha256:4cae47d1b2d426316b85a0087d9e69e048f13bc003b5177d74639fe9dfd28205", size = 15625488, upload-time = "2026-06-23T02:47:03.192Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/46/05b227b34e434b54867c2c942b0bfbbe2fe41789c18bb15ef787d03e9a56/botocore-1.43.27-py3-none-any.whl", hash = "sha256:4976544e652d5a1d8eca135da019f8e1c2d749efa2f9a31a8fb8c76f1895a40b", size = 15190293, upload-time = "2026-06-10T19:38:22.298Z" }, + { url = "https://files.pythonhosted.org/packages/5c/19/934f81592527a3f7f9b943c893e334c721a4644948642bc33885d584e9ec/botocore-1.43.36-py3-none-any.whl", hash = "sha256:3c65fdc39ed01d8dfde1e961b34038aed03c459f8ddf80717a12ac006475e49d", size = 15313630, upload-time = "2026-06-23T02:46:59.327Z" }, ] [[package]] name = "certifi" -version = "2026.5.20" +version = "2026.6.17" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/ce/ee2ecad540810a79593028e88299baeae54d346cc7a0d94b6199988b89b1/certifi-2026.5.20.tar.gz", hash = "sha256:69dea482ab64caa7b9f6aba1c6bf48bb6a5448d1c0f1b17ab42ad8c763a5344d", size = 135422, upload-time = "2026-05-20T11:46:50.073Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c9/c7/424b75da314c1045981bd9777432fad05a9e0c69daa4ed7e308bbaffe405/certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432", size = 134594, upload-time = "2026-06-17T10:31:07.894Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/8c/57e832b7af6d7c5abe66eb3fbe3a3a32f4d11ea23a1aa7131371035be991/certifi-2026.5.20-py3-none-any.whl", hash = "sha256:3c52e209ba0a4ad7aebe60436a4ab349c39e1e602e8c134221e546902ad25897", size = 134134, upload-time = "2026-05-20T11:46:48.578Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2f/c5464532e965badff2f4c4c1a3a83f5697f0d7c407ed0cda44aaa99bb451/certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db", size = 133289, upload-time = "2026-06-17T10:31:06.348Z" }, ] [[package]] name = "crowdsec-service-api" -version = "1.128.0" +version = "1.132.2" source = { editable = "." } dependencies = [ { name = "botocore" },