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