diff --git a/.github/wordlist.txt b/.github/wordlist.txt index da68108b3..8c65af328 100644 --- a/.github/wordlist.txt +++ b/.github/wordlist.txt @@ -83,6 +83,8 @@ FalconShell FalconX Falconx FalconXSandbox +FileVantage +filevantage FirewallManagement FlightControl GCP diff --git a/CHANGELOG.md b/CHANGELOG.md index fa3e99b01..d13a57323 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ +# Version 0.8.11 +## Added features and functionality ++ Added: FileVantage Service Class and all related endpoints. + - `_endpoint/_filevantage.py` + - `_endpoint/__init__.py` + - `filevantage.py` + - `tests/test_filevantage.py` + # Version 0.8.10 ## Added features and functionality -+ Added: MessageCenter Service Class. ++ Added: MessageCenter Service Class and all related endpoints. - `_endpoint/_message_center.py` - `_endpoint/__init__.py` - `_payload/_message_center.py` diff --git a/README.md b/README.md index fc16f688a..2b1878e17 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Representing a single API service collection, each service class has a method de | [CrowdStrike Falcon Container](https://falcon.crowdstrike.com/documentation/146/falcon-container-sensor-for-linux) | [falcon_container.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/falcon_container.py) | | [CrowdStrike Falcon Horizon](https://falcon.crowdstrike.com/support/documentation/137/falcon-horizon-apis) | [cspm_registration.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/cspm_registration.py) | | [CrowdStrike Falcon X](https://falcon.crowdstrike.com/support/documentation/92/falcon-x-apis) | [sample_uploads.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/sample_uploads.py)
[falconx_sandbox.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/falconx_sandbox.py)
[quick_scan.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/quick_scan.py)| +| CrowdStrike FileVantage | [filevantage.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/filevantage.py) | | [CrowdStrike Firewall Management](https://falcon.crowdstrike.com/support/documentation/107/falcon-firewall-management-apis) | [firewall_management.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/firewall_management.py) | | [CrowdStrike Firewall Policy Management](https://falcon.crowdstrike.com/support/documentation/107/falcon-firewall-management-apis) | [firewall_policies.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/firewall_policies.py) | | [CrowdStrike Falcon Complete Dashboard](https://falcon.crowdstrike.com/documentation/151/falcon-complete-dashboard-apis) | [falcon_complete_dashboard.py](https://github.com/CrowdStrike/falconpy/blob/main/src/falconpy/falcon_complete_dashboard.py) | diff --git a/src/falconpy/README.md b/src/falconpy/README.md index 96c1932f5..19ab81f01 100644 --- a/src/falconpy/README.md +++ b/src/falconpy/README.md @@ -19,6 +19,7 @@ for every single operation available within that service collection. | `falcon_complete_dashboard.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falcon-complete-dashboard | | `falcon_container.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falcon-container | | `falconx_sandbox.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/falconx-sandbox | +| `filevantage.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/filevantage | | `firewall_management.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-management | | `firewall_policies.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/firewall-policies | | `host_group.py` | https://assets.falcon.crowdstrike.com/support/api/swagger.html#/host-group | diff --git a/src/falconpy/__init__.py b/src/falconpy/__init__.py index b26d7b362..b81c577a6 100644 --- a/src/falconpy/__init__.py +++ b/src/falconpy/__init__.py @@ -34,6 +34,7 @@ from .falcon_complete_dashboard import CompleteDashboard from .falcon_container import FalconContainer from .falconx_sandbox import FalconXSandbox +from .filevantage import FileVantage from .firewall_management import FirewallManagement from .firewall_policies import FirewallPolicies from .host_group import HostGroup @@ -89,8 +90,8 @@ "RealTimeResponse", "Recon", "ReportExecutions", "ResponsePolicies", "SampleUploads", "ScheduledReports", "SensorDownload", "SensorUpdatePolicy", "SensorVisibilityExclusions", "SpotlightVulnerabilities", "UserManagement", "ZeroTrustAssessment", "PreventionPolicies", - "SensorUpdatePolicies", "MessageCenter" - ] + "SensorUpdatePolicies", "MessageCenter", "FileVantage" +] """ This is free and unencumbered software released into the public domain. diff --git a/src/falconpy/_endpoint/__init__.py b/src/falconpy/_endpoint/__init__.py index e42a9c4b2..9e0bc3bfa 100644 --- a/src/falconpy/_endpoint/__init__.py +++ b/src/falconpy/_endpoint/__init__.py @@ -42,6 +42,7 @@ from ._falcon_complete_dashboard import _falcon_complete_dashboard_endpoints from ._falcon_container import _falcon_container_endpoints from ._falconx_sandbox import _falconx_sandbox_endpoints +from ._filevantage import _filevantage_endpoints from ._firewall_management import _firewall_management_endpoints from ._firewall_policies import _firewall_policies_endpoints from ._host_group import _host_group_endpoints @@ -89,6 +90,7 @@ api_endpoints.extend(_falcon_complete_dashboard_endpoints) api_endpoints.extend(_falcon_container_endpoints) api_endpoints.extend(_falconx_sandbox_endpoints) +api_endpoints.extend(_filevantage_endpoints) api_endpoints.extend(_firewall_management_endpoints) api_endpoints.extend(_firewall_policies_endpoints) api_endpoints.extend(_host_group_endpoints) diff --git a/src/falconpy/_endpoint/_filevantage.py b/src/falconpy/_endpoint/_filevantage.py new file mode 100644 index 000000000..86161f7e9 --- /dev/null +++ b/src/falconpy/_endpoint/_filevantage.py @@ -0,0 +1,104 @@ +"""Internal API endpoint constant library. + + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" + +_filevantage_endpoints = [ + [ + "getChanges", + "GET", + "/filevantage/entities/changes/v2", + "Retrieve information on changes", + "filevantage", + [ + { + "type": "array", + "items": { + "type": "string" + }, + "collectionFormat": "multi", + "description": "Comma separated values of change ids", + "name": "ids", + "in": "query", + "required": True + } + ] + ], + [ + "queryChanges", + "GET", + "/filevantage/queries/changes/v2", + "Returns one or more change IDs", + "filevantage", + [ + { + "minimum": 0, + "type": "integer", + "description": "The first change index to return in the response. " + "If not provided it will default to '0'. " + "Use with the `limit` parameter to manage pagination of results.", + "name": "offset", + "in": "query" + }, + { + "type": "integer", + "description": "The maximum number of changes to return in the response " + "(default: 100; max: 500). " + "Use with the `offset` parameter to manage pagination of results", + "name": "limit", + "in": "query" + }, + { + "type": "string", + "description": "Sort changes using options like:\n\n" + "- `action_timestamp` (timestamp of the change occurrence) \n\n " + "Sort either `asc` (ascending) or `desc` (descending). " + "For example: `action_timestamp|asc`.\n" + "The full list of allowed sorting options can be reviewed in our API documentation.", + "name": "sort", + "in": "query" + }, + { + "type": "string", + "description": "Filter changes using a query in Falcon Query Language (FQL). \n\n" + "Common filter options include:\n\n - `host.host_name`\n - `action_timestamp`\n\n " + "The full list of allowed filter parameters can be reviewed in our API documentation.", + "name": "filter", + "in": "query" + } + ] + ] +] diff --git a/src/falconpy/_version.py b/src/falconpy/_version.py index a2e7d342e..c5fb39ead 100644 --- a/src/falconpy/_version.py +++ b/src/falconpy/_version.py @@ -35,7 +35,7 @@ For more information, please refer to """ -_VERSION = '0.8.10' +_VERSION = '0.8.11' _MAINTAINER = 'Joshua Hiller' _AUTHOR = 'CrowdStrike' _AUTHOR_EMAIL = 'falconpy@crowdstrike.com' diff --git a/src/falconpy/filevantage.py b/src/falconpy/filevantage.py new file mode 100644 index 000000000..22e2af8f0 --- /dev/null +++ b/src/falconpy/filevantage.py @@ -0,0 +1,125 @@ +"""CrowdStrike FileVantage API Interface Class. + + _______ __ _______ __ __ __ +| _ .----.-----.--.--.--.--| | _ | |_.----|__| |--.-----. +|. 1___| _| _ | | | | _ | 1___| _| _| | <| -__| +|. |___|__| |_____|________|_____|____ |____|__| |__|__|__|_____| +|: 1 | |: 1 | +|::.. . | CROWDSTRIKE FALCON |::.. . | FalconPy +`-------' `-------' + +OAuth2 API - Customer SDK + +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to +""" +from ._util import process_service_request, force_default, handle_single_argument +from ._service_class import ServiceClass +from ._endpoint._filevantage import _filevantage_endpoints as Endpoints + + +class FileVantage(ServiceClass): + """The only requirement to instantiate an instance of this class is one of the following. + + - a valid client_id and client_secret provided as keywords. + - a credential dictionary with client_id and client_secret containing valid API credentials + { + "client_id": "CLIENT_ID_HERE", + "client_secret": "CLIENT_SECRET_HERE" + } + - a previously-authenticated instance of the authentication service class (oauth2.py) + - a valid token provided by the authentication service class (oauth2.py) + """ + + @force_default(defaults=["parameters"], default_types=["dict"]) + def get_changes(self: object, *args, parameters: dict = None, **kwargs) -> dict: + """Retrieve information on changes. + + Keyword arguments: + ids -- Change IDs to retrieve. String or list of strings. + parameters - full parameters payload, not required if ids is provided as a keyword. + + Arguments: When not specified, the first argument to this method is assumed to be 'ids'. + All others are ignored. + + Returns: dict object containing API response. + + HTTP Method: GET + + Swagger URL + https://assets.falcon.crowdstrike.com/support/api/swagger.html#/filevantage/getChanges + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="getChanges", + keywords=kwargs, + params=handle_single_argument(args, parameters, "ids") + ) + + @force_default(defaults=["parameters"], default_types=["dict"]) + def query_changes(self: object, parameters: dict = None, **kwargs) -> dict: + """Search for changes within your environment. Returns one or more change IDs. + + Keyword arguments: + filter -- The filter expression that should be used to limit the results. FQL syntax. + Available filters + action_timestamp ingestion_timestamp + host.name + limit -- The maximum number of records to return. [Integer, 1-500, Default: 100] + offset -- The integer offset to start retrieving records from. + parameters - full parameters payload, not required if using other keywords. + sort -- The property to sort by. FQL syntax (e.g. status.desc or hostname.asc). + Available sort fields + action_timestamp ingestion_timestamp + + + 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#/filevantage/queryChanges + """ + return process_service_request( + calling_object=self, + endpoints=Endpoints, + operation_id="queryChanges", + keywords=kwargs, + params=parameters + ) + + # This method name aligns to the operation ID in the API but + # does not conform to snake_case / PEP8 and is defined here + # for backwards compatibility / ease of use purposes + getChanges = get_changes + queryChanges = query_changes + + +# The legacy name for this class does not conform to PascalCase / PEP8 +# It is defined here for backwards compatibility purposes only. +File_Vantage = FileVantage # pylint: disable=C0103 diff --git a/tests/test_filevantage.py b/tests/test_filevantage.py new file mode 100644 index 000000000..c0d8109dd --- /dev/null +++ b/tests/test_filevantage.py @@ -0,0 +1,35 @@ +""" +test_filevantage.py - This class tests the FileVantage service class +""" +import platform +import os +import sys +import pytest +# Authentication via the test_authorization.py +from tests import test_authorization as Authorization + +# Import our sibling src folder into the path +sys.path.append(os.path.abspath('src')) +# Classes to test - manually imported from sibling folder +from falconpy import FileVantage + +auth = Authorization.TestAuthorization() +token = auth.getConfigExtended() +falcon = FileVantage(access_token=token) +AllowedResponses = [200, 202, 429] # Adding rate-limiting as an allowed response for now + + +class TestFileVantage: + """ + FileVantage Service Class test harness + """ + def test_query_changes(self): + """Pytest harness hook""" + assert bool(falcon.query_changes(limit=1)["status_code"] in AllowedResponses) is True + + def test_get_changes(self): + """Pytest harness hook""" + # Also testing lazy loading of the ids parameter + assert bool( + falcon.get_changes("12345678")["status_code"] in AllowedResponses + ) is True