diff --git a/.gitignore b/.gitignore index 0a71eccf..2ac52fce 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.pyc *.swp *.egg +.idea/* env/ .venv/ .eggs/ @@ -16,4 +17,4 @@ __pycache__/ .coverage htmlcov/ Pipfile* -hold \ No newline at end of file +hold diff --git a/CHANGELOG.md b/CHANGELOG.md index 6227a0d7..f9f9e171 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +# Version 1.5.5 +## Added features and functionality ++ Added: Added new __Cloud Security Compliance__ service collection with 2 new operations. + - `_endpoint/__init__.py` + - `_endpoint/_cloud_security_compliance.py` + - `_endpoint/deprecated/__init__.py` + - `_endpoint/deprecated/_cloud_security_compliance.py` + - `__init__.py` + - `cloud_security_compliance.py` + > Unit testing expanded to complete code coverage. + - `tests/test_cloud_security_compliance.py` + +- Added: Added new _WorkflowDefinitionsStatus_ operation to the __Workflows__ service class. + - `_constant/__init__.py` + - `_endpoint/_workflows.py` + - `workflows.py` + > Unit testing expanded to complete code coverage. + - `tests/test_workflows.py` + - Special thanks go out to @dweissbacher for contributing this update and related unit tests! 🙇 + +## Issues resolved ++ Fixed: Resolved path interpolation issue for the `search_id` keyword when using the Uber Class to call the _GetSearchStatusV1_ operation. Closes #1365. + - `_util/_uber.py` + - Thanks go out to @yakeeliuliu for reporting this issue! 🙇 + ++ Fixed: Resolved body payload generation issue with the _userActionV1_ operation within the __UserManagement__ service class. + - `user_management.py` + ++ Fixed: Resolved availability issue with FDR service collection endpoints within the endpoint module. Closes #1371. + - `_endpoint/__init__.py` + > Thanks go out to @Don-Swanson-Adobe for reporting this issue! 🙇 + +## Other + +--- + # Version 1.5.4 ## Added features and functionality + Added: Added _tag_key_ and _tag_value_ as allowed values for the `filter` parameter in the _cloud_security_assets_combined_compliance_by_account_ operation within the __Cloud Security Assets__ service collection. diff --git a/src/falconpy/_endpoint/_sensor_usage.py b/src/falconpy/_endpoint/_sensor_usage.py index e8c35a0c..fb1c8df2 100644 --- a/src/falconpy/_endpoint/_sensor_usage.py +++ b/src/falconpy/_endpoint/_sensor_usage.py @@ -58,5 +58,27 @@ "in": "query" } ] + ], + [ + "GetSensorUsageHourly", + "GET", + "/billing-dashboards-usage/aggregates/hourly-average/v1", + "Fetches hourly average. Each data point represents the average of how many unique AIDs were seen per week " + "for the previous 28 days.", + "sensor_usage", + [ + { + "type": "string", + "description": "The FQL search filter. Allowed fields:\n\"event_date\" : A specified date that will be " + " final date of the results returned. Specified date cannot be after the default.\n\tFormat: " + "'2024-06-11'\n\tDefault: the current date, minus 2 days, in UTC\n\"period\" : An integer surrounded by single " + "quotes representing the number of days to return.\n\tFormat: '30'\n\tDefault: '28'\n\tMinimum: '1'\n\tMaximum: " + " '395'\n\"selected_cids\" : A comma separated list of CIDs to return data for. Caller must be a parent CID or " + "have special access enabled.\n\tFormat: 'cid_1,cid_2,cid_3'\n\tDefault: for parent CIDs the default is the " + "parent and all children, otherwise the current CID", + "name": "filter", + "in": "query" + } + ] ] ] diff --git a/src/falconpy/_util/_functions.py b/src/falconpy/_util/_functions.py index 071e5549..f887e87d 100644 --- a/src/falconpy/_util/_functions.py +++ b/src/falconpy/_util/_functions.py @@ -41,9 +41,10 @@ from warnings import warn from json import loads try: - from simplejson import JSONDecodeError -except (ImportError, ModuleNotFoundError): # Support import as a module - from json.decoder import JSONDecodeError + from simplejson import JSONDecodeError as SimplejsonJSONDecodeError +except (ImportError, ModuleNotFoundError): + SimplejsonJSONDecodeError = None # Support import as a module +from json.decoder import JSONDecodeError as StdJSONDecodeError from typing import Dict, Any, Union, Optional, List, TYPE_CHECKING from copy import deepcopy from logging import Logger @@ -85,6 +86,9 @@ urllib3.disable_warnings(InsecureRequestWarning) +# create a tuple of all possible JSONDecodeError types for exception handling +JSONDecodeError = (SimplejsonJSONDecodeError, StdJSONDecodeError) if SimplejsonJSONDecodeError else (StdJSONDecodeError,) + def validate_payload(validator: Dict[str, Any], payload: Dict[str, Union[str, int, dict, list, bytes]], diff --git a/src/falconpy/sensor_usage.py b/src/falconpy/sensor_usage.py index d9ad0bbf..cf02ecad 100644 --- a/src/falconpy/sensor_usage.py +++ b/src/falconpy/sensor_usage.py @@ -97,4 +97,48 @@ def get_weekly_usage(self: object, parameters: dict = None, **kwargs) -> Union[D params=parameters ) + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_hourly_usage(self: object, parameters: dict = None, **kwargs) -> Union[Dict[str, Union[int, dict]], Result]: + """Fetch hourly sensor usage average used to measure cloud usage. + + Each data point represents the average of how many unique AIDs were seen per week for the previous 28 days. + + Keyword arguments: + filter -- The FQL search filter. + Allowed fields: + event_date - A specified date that will be final date of the results returned. + Specified date cannot be after the default. + Format: '2024-06-11' + Default: the current date, minus 2 days, in UTC + period - An integer surrounded by single quotes representing the number of days to return. + Format: '30' + Default: '28' + Minimum: '1' + Maximum: '395' + selected_cids - A comma delimited list of CIDs to return data for. + Caller must be a parent CID or have special access enabled. + Format: 'cid_1,cid_2,cid_3' + Default: for parent CIDs the default is the parent and all children, + otherwise the current CID + parameters -- Full parameters payload dictionary. Not required if using other keywords. + + This method only supports keywords for providing arguments. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/sensor-usage-api/GetSensorUsageWeekly + Endpoint is not in Swagger file, but allows you to pull `hourly` usage which is used to determine cloud usage + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="GetSensorUsageHourly", + keywords=kwargs, + params=parameters + ) + GetSensorUsageWeekly = get_weekly_usage + GetSensorUsageHourly = get_hourly_usage diff --git a/tests/test_sensor_usage.py b/tests/test_sensor_usage.py index 8870bfce..a0aab111 100644 --- a/tests/test_sensor_usage.py +++ b/tests/test_sensor_usage.py @@ -23,7 +23,8 @@ class TestSensorUsage: def test_all_code_paths(self): error_checks = True tests = { - "GetWeeklySensorUsage": falcon.get_weekly_usage() + "GetWeeklySensorUsage": falcon.get_weekly_usage(), + "GetHourlySensorUsage": falcon.get_hourly_usage() } for key in tests: if tests[key]["status_code"] not in AllowedResponses: