From b9bc7b5d722331cf14cf9d1ab25d280fa20f16d8 Mon Sep 17 00:00:00 2001 From: he2ss <19668340+he2ss@users.noreply.github.com> Date: Mon, 27 Jul 2026 15:18:36 +0000 Subject: [PATCH] Update python SDK V0.18.1 --- crowdsec_service_api/__init__.py | 9 +- .../__pycache__/__init__.cpython-311.pyc | Bin 5024 -> 5163 bytes .../__pycache__/base_model.cpython-311.pyc | Bin 4378 -> 4370 bytes .../__pycache__/http_client.cpython-311.pyc | Bin 7768 -> 7760 bytes .../__pycache__/models.cpython-311.pyc | Bin 158635 -> 166867 bytes crowdsec_service_api/models.py | 420 +++++-- .../__pycache__/__init__.cpython-311.pyc | Bin 207 -> 199 bytes .../__pycache__/allowlists.cpython-311.pyc | Bin 12917 -> 12909 bytes .../__pycache__/blocklists.cpython-311.pyc | Bin 15121 -> 15113 bytes .../services/__pycache__/cves.cpython-311.pyc | Bin 12321 -> 12356 bytes .../__pycache__/decisions.cpython-311.pyc | Bin 4338 -> 7214 bytes .../__pycache__/fingerprints.cpython-311.pyc | Bin 12310 -> 12345 bytes .../services/__pycache__/hub.cpython-311.pyc | Bin 3277 -> 3269 bytes .../services/__pycache__/info.cpython-311.pyc | Bin 2035 -> 2027 bytes .../__pycache__/integrations.cpython-311.pyc | Bin 8075 -> 8067 bytes .../__pycache__/metrics.cpython-311.pyc | Bin 2607 -> 2599 bytes .../__pycache__/products.cpython-311.pyc | Bin 3782 -> 3774 bytes .../tracker_events.cpython-311.pyc | Bin 2914 -> 2906 bytes .../__pycache__/tracker_tags.cpython-311.pyc | Bin 5698 -> 5690 bytes .../__pycache__/vendors.cpython-311.pyc | Bin 10351 -> 10343 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 | 9 +- doc/Cves.md | 6 +- doc/Decisions.md | 152 ++- doc/Fingerprints.md | 6 +- doc/Models.md | 107 +- doc/README.md | 16 +- public-openapi.json | 1092 ++++++++++++++--- pyproject.toml | 2 +- uv.lock | 38 +- 42 files changed, 1603 insertions(+), 360 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..13f79d1db99b5f9c6e54fb038d8d419c4fc5fc62 100644 GIT binary patch delta 284 zcmZ3WzFLECIWI340}vc3OV7#`-N;wPBp0Zkk)NBYUsRfxms+GBU!Gr-tzT4@s+(Al z38W{lW6EIMHd&n6#W6j-C^bE?BsIk)H9505Ge6I>BsKSz9Hw}&dumBgYH>k+UUBLz zC4~HBSq@1lNdzBePH}L4QHfLK<_P9a7JU(zsBdC&MrK}Wa0$@LTN2nrUGqwFH$Py% z$Sfl49OeqM(IvGcF*7GMW%5DpYn#{e77N<^5;khO*=9Zb4 zo?28;l$lo&RGO0-T$-DkSX8;$k~f!?@#5y?LYa)xMNHgG9~cm113L&7$p9S&05`@q ABme*a diff --git a/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc b/crowdsec_service_api/__pycache__/base_model.cpython-311.pyc index 98b9f58568825bc4f734f1e579444f5920d5390c..d4ec602c55f06cdefce467b59d662f7e3afd3056 100644 GIT binary patch delta 56 zcmbQGG)akjIWI340}yO2OW(+?%q$nIpOK%Ns$W!^mzP?kA77qdl&xP>ma3arkO`zW JhcF-G1pv-)5%mB7 delta 64 zcmbQFG)swlIWI340}wnd(b~wZ%&ZozpOK%Ns$W!^mzP?kA77qdl&znfpI4lpld79o NkO^gP_F+E83jlAr6*>R_ diff --git a/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc b/crowdsec_service_api/__pycache__/http_client.cpython-311.pyc index 1bc5815900c09dcc5d59b8b7d1636dda5e5ee5f9..aeec675aed504750d4e8b66bf37f946b806eaf6d 100644 GIT binary patch delta 56 zcmca%bHRptIWI340}yO2OW(+Sj!`Z|KO;XkRlle-FE6!7KfXM_C|kd%ELAtLAQMP$ J{?8aG0{{;(6Pf@3 delta 64 zcmca$bHj#vIWI340}wnd(b~v;j!`W}KO;XkRlle-FE6!7KfXM_C|f@{Kd(4HCsjAG NAQQ^o{GBmU1^~M}7T*8> diff --git a/crowdsec_service_api/__pycache__/models.cpython-311.pyc b/crowdsec_service_api/__pycache__/models.cpython-311.pyc index 6ec2ace3e093ffc22a4a8f92ab2f5aa7fa9fef13..dadacf2f7e07e2270e1aea870ea0f540eee069ff 100644 GIT binary patch delta 38450 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 delta 32722 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 -# timestamp: 2026-06-11T08:42:40+00:00 +# timestamp: 2026-07-27T15:18:28+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', @@ -244,6 +249,13 @@ class BlocklistCreateRequest(BaseModelSdk): tags: Annotated[ Optional[List[str]], Field(description='Classification tags', title='Tags') ] = [] + store_full_content_in_s3: Annotated[ + Optional[bool], + Field( + description='Whether to store the full blocklist content in S3 or not', + title='Store Full Content In S3', + ), + ] = False class BlocklistDeleteIPsRequest(BaseModelSdk): @@ -420,6 +432,12 @@ class DecisionCreateResponse(BaseModelSdk): ] +class DecisionMachineStateEnum(StrEnum): + PENDING_CREATE = 'PENDING_CREATE' + PENDING_DELETE = 'PENDING_DELETE' + APPLIED = 'APPLIED' + + class DecisionTargetType(StrEnum): ORG = 'org' TAG = 'tag' @@ -670,10 +688,13 @@ class CVEEventOutput(BaseModelSdk): class CVEExploitationPhase(StrEnum): INSUFFICIENT_DATA = 'insufficient_data' EARLY_EXPLOITATION = 'early_exploitation' + RAPID_ESCALATION = 'rapid_escalation' + ACTIVE_EXPLOITATION = 'active_exploitation' + BACKGROUND_NOISE = 'background_noise' + LIMITED_EXPLOITATION = 'limited_exploitation' FRESH_AND_POPULAR = 'fresh_and_popular' TARGETED_EXPLOITATION = 'targeted_exploitation' MASS_EXPLOITATION = 'mass_exploitation' - BACKGROUND_NOISE = 'background_noise' UNPOPULAR = 'unpopular' WEARING_OUT = 'wearing_out' UNCLASSIFIED = 'unclassified' @@ -1380,7 +1401,7 @@ class BlocklistsUploadBlocklistContentQueryParameters(BaseModelSdk): Optional[datetime], Field( description='Blocklist expiration', - examples=['2026-06-11T08:40:13.370581+00:00'], + examples=['2026-07-08T08:42:28.511313+00:00'], title='Expiration', ), ] = None @@ -1587,6 +1608,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 +1646,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 +1686,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 +1884,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 +2320,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 +2798,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 +3889,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 +3969,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 +4076,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 +4191,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 +4200,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 +4527,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..2c73aef951ee57ef99f5a65895815ffe87d95908 100644 GIT binary patch delta 38 scmX@lc$|@YIWI340}yO2OP|PX${01#QJAZ!ELAtLAXC4nY+_m_0LKRlM*si- delta 46 wcmX@kc%G4aIWI340}wnd(VEC@%9u3KQCKKBKd(4HCsjAGAX6X0o*0)205BI0i~s-t diff --git a/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/allowlists.cpython-311.pyc index 43c12d0fa29acc733d3ff5413d13fc4bbf224419..6c0153ac5211798da2befdc1476e5e22301369ca 100644 GIT binary patch delta 68 zcmeyG@-~HgIWI340}vc3OW(*H%gi2Tpl4{IXE-^ZIY=%>KO;XkRlle-FE6!7KfXM_ VC|kd%ELAtLAQMP$e$L#d2LR#d7S{j( delta 76 zcmaEx@->BfIWI340|=CAZRCz+W;fI`G_ue$n4HfXq?V$ek)NBYUsRfxms+GBU!Gr- Yt)HBqSDc@ds+(Al31x4-&)la60AeE<1poj5 diff --git a/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/blocklists.cpython-311.pyc index d87cdb1bac7f4880ebeb44a85f3d6e4d5ffdd4cb..89b3ae03dd4e094b272c90e57c6fb4b2d45df063 100644 GIT binary patch delta 68 zcmbPO)>+2AoR^o20SJzirElcE%gi2Tpl4{IXE^yibC6t&enx(7s(w*vUS4XEetda; VQMP_jS*mVgK_-yioX)b!3;^Mq7T5p) delta 76 zcmeAyn^?xZoR^o20R&35Hgex(W;fI`G_ue$nEakONG(M_BR@A)zo;}XFSSTNzC6Du YTR%BJuQ)#^RX4F96UyEk&$7x40A#iq1^@s6 diff --git a/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/cves.cpython-311.pyc index 7d05d919d947b7bbc0e723946bb4f0ca957ad427..9bbd33bad7980cd30934dbb3c454946337ee67eb 100644 GIT binary patch delta 2202 zcma)8UrbwN6u)1&{mZ>AE&U5E6k6yXMmsi;0d7kM5sc1d8<`t%Y{>T&i=}NoIvfrp z#wFuH$(HY7Q)A*x)EG_7Qs;vYOH8JZW-&Z0jd4qSTehS`A56?L&$*QVlRvx7{oU_( z?)lE|oO92;>GiX>&#GUlszrk1_RPfO;0<+v)Z3B5@#k+uk}gSCB_@p!Dvju9i^!0n z1zMdlQiYkA?5j8eQWdyi9k&8EuH!b~=5@S=S*V>=QwN+fQ&Kgw_M(17rA{UTx29z3 zx+ss>{^K>k-N5a@7tlclg9i)_vxGm|syX_eN@`7@Hf5o8Am9Yw$fmwBbEOQl9(>$d z#Hi-A7QvG;Q9s=EcG3Xz;Y~=P0aB>b92+$r1YQpkG0mnjKW&1P0<1yY*Le;GSmRm; zAY3zq3u>Mr)&xZbSo6C31{#KFp+)ID83`YkVsY_Y)z8KgyAvJz5*?ySKGtv|`9^Mv zCHc8*mht47w{rZ=B%fjJWBD{(#Rd5j@`CW{`#dJf3S;REqa`^%Ho;2rboy;JZW1dt zr^Nyf`Km<8yh&U()$7e^Y2G5PH+jTkRT24mnV7|jr%zuEc15WEP|`G~%vH}>zLCF> zCFyH8E62QAu&u6P9t>1JC#A`pD$3Pu;yuIn#437?p>7@pr;@_5G@nan3un&pOsOi9 z8|S;h&XWiU^e}NYozG>b*|ZgCP%Ig{WvAqA6gQ%t;(g;!#2-iBT?l&sVkW*9*PRGm z;zx6XcoZ`0c#n8su5Ubu);@&i5jJY^{o-52EqX0(5-%RLJlrAlDJ8xddPxbAe%L%j z4ix`ZZtbw~S8FS7RCy2NP?8Jme1YR`w+P#!xRo8Uens9 zqbshXXGoVe2)??#_9$)r%;G^n;_a!%7h*@|Y?!!P_%Vw*>OUC@z zY$i8GVW#wfljOVNXh8j6k2h*vYV1O-&XR$$3@fmhxuT{CF_hd&4MbL49#Ingzpg#n$zSTF&yf0Z1RqL9Ew%C-Yh;1ImPcGTW@8eKy$TZEr}2& zF}Xt~k?;WdqnHVQur7;%$P~sRC1p50#WLwEd$GW#cn*xyI)Gr1`!OsRlaT~*iVq{5 zn}1e8H}+*lV+n)@>qNpedIWd-a&*WfEeM2#r0S%X%RPL`62oB zTn;`+@MYq?=yCwz5W)b$Ai@yB%LvC1jw8H^a1!A(!l;;thYb{$X>ldq){w>JIe?OK zJe?h9NAiUuKb=T=G+r9b$QkD?!+dS8*-k&e)HIqSd z)Lm;|wnxiGjhiG_;7*`@*_kMtHG@S8wA^XwS@!pqt2Kin)q2XRwzNt%N7<$=Yj9an zaY$x=xfZR?isAPV+3BreowPXIsk9RDW3h&@Soi4fl8t(S&matJcs`m)%) OQn~xrHcmVMasLII4%D;& delta 2178 zcma)6OH5l=5WUwtf1d4!vGIqGjSU9u$H$ICzL2CUphA>>6q5c>NojYe{ z-uSIe-kwxGR}?G3&qCLQ$ci#dn;n7@^5;*KkPpaB!pJz)$hbiZ^AsIjnlWiMW?@p} zW*i}!9k{8AE5OZFycW1z#U0G5)xlR{wwYSZdDS>>*IY~juFObU{Z(nac9T1RyMfnj za%pBs(mddB$^`$kc5&c)qM(X^YsRWIfIvOOc5E9fF*mf-2r(X!u~S4=H+jsI}#yZ!?*ldwC5i04LCHDX3Uc$&D;5u=^j=1 zkU5+v+F4r5W|HaL`2{^ytVw02^*99UF@#=#qD5!(Sty##D?s_O`LN_74M9HT^%WkN zzoUK?L%R_Y0IEgbk9Hrz0lqG`*bbq27~u$iC^rXBpxKWwfUs3hKgL(>UVhT*rD|c) z`r97)XYE~E@-N#%bPzI((&GiQvbx9Zd$pb3s_LMcqLgEoayq8)@;*nDo-Ukoj2K!g zP42^*MW^zXPS>0&J;d)jqkP?OLrKpT1WZ^Im(JhW>6i2s(*Ic!S(l4GkMi+ z%I1>rD$_5a{|bN5)kk0E;qJGW+@7D^-jc&-9Hu3L_>04LtLDSSl2N!!#MN}Gcf%Pi znFY5HPhdUJyWx(NWZ|%qK*xH=(G7op$tE0j;&7D|Vb-EqPF+W2f5|DlLZz%#A|~P5 zU+C$%V4!{cX6%Y8-k13L)}08rIeGvApWGwMvAK-4kYXqFkN7}*_0)(&2chzv|6M!$ MNBQ)xU4n$bzmi(Lp#T5? diff --git a/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/decisions.cpython-311.pyc index d705642e1226909db262b964ed97acbc6e614089..fc418853f576d49c95456d7340480a98ba746b62 100644 GIT binary patch literal 7214 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 ZO}Q$baS8BR+S8AGU+|tUx9I2k_!pHJtD67- delta 1174 zcmZ`%O>7fK7@cu;y+8Ka@p`@fiv_8HvV_D5lr+$gABqwxdZ46-#uBoOX9A{<*Bv`5 zw4u2~P^lFPnn)nQfm4v6EvnLUuT<&NUvFm%Aj!oCZ({&VC*n2ie!z<-;JTm?4(21STKF@RFE22)GtK<5bn97M_* z1mHfKoxwZ>sjqrSL;9SGLRiI8`b8l?;ceR3rX$;Q6l*xh_J6V!fx4NYyc8J2Ix^Xm zaA?j%@nyLfMiw@hj?76Yu`Cs%$i~uK03{jk{uW$>#n=pR()3E#@5<1?(1DSGLHe0= zdQYWr-krw;z^D2IqXTz>Q}g;(I;{aYP76nWxWb6hv;?9rel^N z2diLFr>CqBv)LJ!BlJ-)0VDK_Xg`fB4+Bn={-yK} zd0|{f4Yyivl@>_N>#DgG!mmb#I1DoIRDzog_HwuxWs-iZo{(&i+C_itPOd*te}U6| zymXSmr({1vM^VcS)dM)^|B zEh92cpXtY7-}+eSPuRl`B?BB@kEi`c-$*B)6?j2}Yq*6Sm1KDRG>5mH#tvCACgBAA z!=Rc2iOGr`lisptZK+mmwg_*o*Tq^#MtRNz)sxxKaZaZ=oTR1X!N5GEtI3&Aes?>! zqy4VaPG>1hWtZAkqHWoJJS~3&eZcW=J9G2kYSov86$GZeQdv#=ijXSk*?Fhy_F-QW zQU?)pCI9`b9}+SQ%*@TgBGlr56uuNGtAB*-xRF7vf>gggA#5VrURovI$@{jZMByJ(?? c$H*C4$o@Jx1)=4GH{*)(RIF^iWnIKR2Xd1JM*si- diff --git a/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/fingerprints.cpython-311.pyc index 43a3794d6559f7bed7b0eeec2036e4ad35245093..f327048a1985a92b8c98965df4df09cee4f755e1 100644 GIT binary patch delta 2287 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 delta 76 zcmX>qc~+8pIWI340|=CAZRD2k)NBYUsRfxms+GBU!Gr- Yt)HBqSDc@ds+(Al31x4-&LqML04d@ZlK=n! diff --git a/crowdsec_service_api/services/__pycache__/integrations.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/integrations.cpython-311.pyc index 53c1b9a9ec792af93fa36c27f740d87492cd99cb..676301e4aa4148311684d11fd03e653459408fb7 100644 GIT binary patch delta 68 zcmeCSZ?@-N&dbZi00c+M(l>IeGqZ;o=own*8BVrj4w8%0&&bbB)h{Z|%S$cNk1x+J V%GNI`OVv#*$OO`xH!|On1^|SG6;c2I delta 76 zcmZp+@3!Y&&dbZi00O028@bh)*$wp!jV$yGCR;KGsio;>nG>u73b%q>LwOsLfM;FGT)L00QhkifB*mh diff --git a/crowdsec_service_api/services/__pycache__/metrics.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/metrics.cpython-311.pyc index 3dd88f559c910ce5387a7850a10836d8cccbb337..c8901ee69fcd71a67eba3830a4b8fdaea52ca8d7 100644 GIT binary patch delta 68 zcmZ24vRs6FIWI340}vc3OW(*ngNZ%NK+n)Z&v5c8rXaaU{fzwFRQ;mTyu8#R{rK|y VqHO)5vQ*u~f=nR2S&5mK9RQ<>6t4gP delta 76 zcmZ23vR;IHIWI340|=CAZRDQ8#BQi(Xk?*hFnJYIkXoXCMt*Lpeo<*&UTTqke0hFR YwtjMcUU7a-s%~OICX~HdikX)k03GcX-2eap diff --git a/crowdsec_service_api/services/__pycache__/products.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/products.cpython-311.pyc index 46ae2eb243d215432d14d619a14b512bbe5e3d54..e203ef020f219ec68807133cadd805dfbdf6e3bf 100644 GIT binary patch delta 68 zcmX>myHA#TIWI340}vc3OW(+SpNT!pK+n)Z&v5cbrXaZ}{fzwFRQ;mTyu8#R{rK|y VqHO)5vQ*u~f=nR2Ig>e-8vxGA78w8l delta 76 zcmdlddrX#lIWI340|=CAZREbs#BQi(Xk?*hF!>`>kXn*{Mt*Lpeo<*&UTTqke0hFR YwtjMcUU7a-s%~OICX~H7kvWzd08gbDM*si- 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..2aaa795b809541b59e9956487b439fcf0463a38d 100644 GIT binary patch delta 54 zcmaDPc1w(VIWI340}vc3OW(+ShKW7QK+n)Z&v5cRrXa?I$%f3rTt#K6x`_pu`bA}% I!%+5M#zSVh1OT!}72*H@ delta 76 zcmdm`b4Z7KIWI340|=CAZR9RtW;fI`G_ue$nB2x3q?V?ik)NBYUsRfxms+GBU!Gr- Yt)HBqSDc@ds+(Al31x5o#_S>l04-7&5C8xG diff --git a/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc b/crowdsec_service_api/services/__pycache__/vendors.cpython-311.pyc index d4f743a50282e1bb623c56cac65a0e44cf40b373..ce72ba2acdfe53ad3fc8e970d904bdccdc8ad4b7 100644 GIT binary patch delta 68 zcmaDK@H~KfIWI340}vc3OW(+SjF~;mK+n)Z&v5b$<{-I9{fzwFRQ;mTyu8#R{rK|y VqHO)5vQ*u~f=nR2IeXk?*hF!=^^kXoXCMt*Lpeo<*&UTTqke0hFR YwtjMcUU7a-s%~OICX~I|gGF8i0D4{+kpKVy diff --git a/crowdsec_service_api/services/allowlists.py b/crowdsec_service_api/services/allowlists.py index 057a909..658434e 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/V0.18.1") def list_allowlists( self, diff --git a/crowdsec_service_api/services/blocklists.py b/crowdsec_service_api/services/blocklists.py index ac2cad5..e543a43 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/V0.18.1") def get_blocklists( self, diff --git a/crowdsec_service_api/services/cves.py b/crowdsec_service_api/services/cves.py index 6d90155..1825c8e 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/V0.18.1") 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..96ba64d 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/V0.18.1") 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..01a2879 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/V0.18.1") 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..14b9eee 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/V0.18.1") def get_index( self, diff --git a/crowdsec_service_api/services/info.py b/crowdsec_service_api/services/info.py index c5b2050..8a2d3bc 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/V0.18.1") def get_info( self, diff --git a/crowdsec_service_api/services/integrations.py b/crowdsec_service_api/services/integrations.py index 73f5656..f864e6f 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/V0.18.1") def get_integrations( self, diff --git a/crowdsec_service_api/services/metrics.py b/crowdsec_service_api/services/metrics.py index 322c7c5..d799f0b 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/V0.18.1") def get_metrics_remediation( self, diff --git a/crowdsec_service_api/services/products.py b/crowdsec_service_api/services/products.py index 5d173fc..e9b7a0c 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/V0.18.1") def get_products( self, diff --git a/crowdsec_service_api/services/tracker_events.py b/crowdsec_service_api/services/tracker_events.py index fa41f55..792a285 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/V0.18.1") 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..6ecc7df 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/V0.18.1") def get_tags( self, diff --git a/crowdsec_service_api/services/vendors.py b/crowdsec_service_api/services/vendors.py index dab3932..0ab5014 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/V0.18.1") def get_vendors( self, diff --git a/doc/Blocklists.md b/doc/Blocklists.md index 78168f1..01e7143 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 @@ -99,6 +99,7 @@ request = BlocklistCreateRequest( description=None, references=None, tags=None, + store_full_content_in_s3=None, ) try: response = client.create_blocklist( @@ -178,7 +179,7 @@ except HTTPStatusError as e: ### Errors: | Code | Description | | ---- | ----------- | -| 404 | Blocklist not found | +| 404 | Not found | | 422 | Validation Error | ### Usage @@ -251,8 +252,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..24032b4 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 @@ -273,6 +331,7 @@ name, description | description | str | Blocklist description || | references | list[str] | Useful references on the list's origins || | tags | list[str] | Classification tags || +| store_full_content_in_s3 | bool | Whether to store the full blocklist content in S3 or not || # **BlocklistDeleteIPsRequest** ## Required: @@ -553,6 +612,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 @@ -1105,9 +1177,9 @@ name, date, description, label, sorting_priority # **CVEExploitationPhase** ## Enum: -INSUFFICIENT_DATA, EARLY_EXPLOITATION, FRESH_AND_POPULAR, TARGETED_EXPLOITATION, MASS_EXPLOITATION, BACKGROUND_NOISE, UNPOPULAR, WEARING_OUT, UNCLASSIFIED +INSUFFICIENT_DATA, EARLY_EXPLOITATION, RAPID_ESCALATION, ACTIVE_EXPLOITATION, BACKGROUND_NOISE, LIMITED_EXPLOITATION, FRESH_AND_POPULAR, TARGETED_EXPLOITATION, MASS_EXPLOITATION, 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 +1202,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 +1327,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 +1404,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 +1438,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..52d0652 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.50", "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-07-08T08:42:28.511313+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": "Unprocessable entity" + }, + "404": { + "description": "Not found" }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - } + "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": { @@ -7210,6 +7936,12 @@ "title": "Tags", "description": "Classification tags", "default": [] + }, + "store_full_content_in_s3": { + "type": "boolean", + "title": "Store Full Content In S3", + "description": "Whether to store the full blocklist content in S3 or not", + "default": false } }, "additionalProperties": false, @@ -8247,6 +8979,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": { @@ -11268,17 +12029,20 @@ "enum": [ "insufficient_data", "early_exploitation", + "rapid_escalation", + "active_exploitation", + "background_noise", + "limited_exploitation", "fresh_and_popular", "targeted_exploitation", "mass_exploitation", - "background_noise", "unpopular", "wearing_out", "unclassified" ], "title": "CVEExploitationPhase" }, - "CVEResponseBase": { + "CVEResponseDetailed": { "properties": { "id": { "type": "string", @@ -11421,6 +12185,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 +12255,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 +12696,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 +13038,7 @@ "properties": { "items": { "items": { - "$ref": "#/components/schemas/CVEResponseBase" + "$ref": "#/components/schemas/CVEResponseDetailed" }, "type": "array", "title": "Items" @@ -12459,7 +13147,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..8bcd6fc 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 = "V0.18.1" license = { text = "MIT" } authors = [ { name="crowdsec", email="info@crowdsec.net" } diff --git a/uv.lock b/uv.lock index 2dd3cda..d123a11 100644 --- a/uv.lock +++ b/uv.lock @@ -4,52 +4,52 @@ requires-python = ">=3.11" [[package]] name = "annotated-types" -version = "0.7.0" +version = "0.8.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/56/a8120250d128bed162cd73c76d45f6ef9991f3e068f62a8ee060afa3104a/annotated_types-0.8.0.tar.gz", hash = "sha256:13b2beaad985e05e2d6407ee4c4f35590b11f8d693a258a561055cac8f64cab7", size = 15893, upload-time = "2026-07-23T20:16:13.995Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, + { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" }, ] [[package]] name = "anyio" -version = "4.13.0" +version = "4.14.2" 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/61/cc/a381afa6efea9f496eff839d4a6a1aed3bfafc7b3ab4b0d1b243a12573dd/anyio-4.14.2.tar.gz", hash = "sha256:cfa139f3ed1a23ee8f88a145ddb5ac7605b8bbfd8592baacd7ce3d8bb4313c7f", size = 260176, upload-time = "2026-07-12T20:29:07.082Z" } 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/da/35/f2287558c17e29fafc8ef3daf819bb9834061cfa43bff8014f7df7f63bdc/anyio-4.14.2-py3-none-any.whl", hash = "sha256:9f505dda5ac9f0c8309b5e8bd445a8c2bf7246f3ce950121e45ea15bc41d1494", size = 125813, upload-time = "2026-07-12T20:29:05.763Z" }, ] [[package]] name = "botocore" -version = "1.43.27" +version = "1.43.56" 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/b9/cc/7f84a5d3071fe878380e9f610ab36ca87b8cbbc4aa81ba2727f90e1f3ea3/botocore-1.43.56.tar.gz", hash = "sha256:6c01f85f0ff9863076f4c761e74ee3aa96c5ccc1ad09fc1efd62ef8f2d22bf57", size = 15733117, upload-time = "2026-07-24T19:31:38.125Z" } 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/cd/86fe9e659e9699f62f8dd5ecd8c6725474334b23cab8aa71d82b5f56f1a4/botocore-1.43.56-py3-none-any.whl", hash = "sha256:aafc741f1b10f6fd63253eaf6ea029680c1ff436d87e1b8969d62aefa0c76976", size = 15418773, upload-time = "2026-07-24T19:31:34.758Z" }, ] [[package]] name = "certifi" -version = "2026.5.20" +version = "2026.7.22" 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/a3/c2/24167ea9858356b47a87a50d39908bfdb72ceeefe0041586e704e5376b3a/certifi-2026.7.22.tar.gz", hash = "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55", size = 138112, upload-time = "2026-07-22T03:35:12.644Z" } 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/0b/a7/71ac2cff56fec219ed242bb11b8efb69fcc4bec75db06fb7bfe35de520e6/certifi-2026.7.22-py3-none-any.whl", hash = "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", size = 136983, upload-time = "2026-07-22T03:35:11.276Z" }, ] [[package]] name = "crowdsec-service-api" -version = "1.128.0" +version = "0.18.1" source = { editable = "." } dependencies = [ { name = "botocore" }, @@ -299,11 +299,11 @@ wheels = [ [[package]] name = "typing-extensions" -version = "4.15.0" +version = "4.16.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" }, ] [[package]] @@ -320,11 +320,11 @@ wheels = [ [[package]] name = "tzdata" -version = "2026.2" +version = "2026.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ff/5a28bdfd8c3ebec42564ac7d0e54ca3db65044a9314a97f9564fa7a1e926/tzdata-2026.3.tar.gz", hash = "sha256:4a1518b8993086a7982523e071643f3c0e5f213e75b21318e78bcabfff9d1415", size = 198674, upload-time = "2026-07-10T08:50:37.887Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, + { url = "https://files.pythonhosted.org/packages/e5/6d/b53b99a9f2766d095985947a5782f1702cabb129a34f7a802d7197af832f/tzdata-2026.3-py2.py3-none-any.whl", hash = "sha256:dc096730c87af6cab1b171c9d532be840741ff5d459015e7f6947bd7d7e54931", size = 348168, upload-time = "2026-07-10T08:50:36.46Z" }, ] [[package]]