Skip to content

Commit

Permalink
Adds Falcon Flight Control Child CID Introspection (#44)
Browse files Browse the repository at this point in the history
* Adds Falcon Flight Control Child CID Introspection

* Add the rest of the Flight Control code and bump dependencies

* Changes to sate pydocstyle

* Bump dependencies again to ensure we have the latest code style versions
  • Loading branch information
ChristopherHammond13 authored Sep 23, 2022
1 parent 8463634 commit fce2e0b
Show file tree
Hide file tree
Showing 8 changed files with 1,036 additions and 121 deletions.
7 changes: 5 additions & 2 deletions caracara/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from caracara.filters.falcon_filter import FalconFilter
from caracara.filters.fql import FalconFilterAttribute
from caracara.modules import (
FlightControlApiModule,
HostsApiModule,
PreventionPoliciesApiModule,
ResponsePoliciesApiModule,
Expand Down Expand Up @@ -147,13 +148,15 @@ def __init__( # pylint: disable=R0913,R0914,R0915
self.logger.info("Resolved Base URL: %s", self.api_authentication.base_url)

# Configure modules here so that IDEs can pick them up
self.logger.debug("Setting up Hosts module")
self.logger.debug("Setting up the Flight Control module")
self.flight_control = FlightControlApiModule(self.api_authentication)
self.logger.debug("Setting up the Hosts module")
self.hosts = HostsApiModule(self.api_authentication)
self.logger.debug("Setting up the Prevention Policies module")
self.prevention_policies = PreventionPoliciesApiModule(self.api_authentication)
self.logger.debug("Setting up the Response Policies module")
self.response_policies = ResponsePoliciesApiModule(self.api_authentication)
self.logger.debug("Setting up RTR module")
self.logger.debug("Setting up the RTR module")
self.rtr = RTRApiModule(self.api_authentication)

self.logger.debug("Configuring FQL filters")
Expand Down
2 changes: 2 additions & 0 deletions caracara/common/batching.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ def worker(batch_func: Callable[[List[str]], Dict], worker_lookup_ids: List[str]
resources_dict[resource['id']] = resource
elif 'device_id' in resource:
resources_dict[resource['device_id']] = resource
elif 'child_cid' in resource:
resources_dict[resource['child_cid']] = resource
else:
raise Exception("No ID field to build the dictionary from")

Expand Down
2 changes: 2 additions & 0 deletions caracara/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
Exposes functions to get host data and perform actions on hosts, such as network containment.
"""
__all__ = [
'FlightControlApiModule',
'HostsApiModule',
'PreventionPoliciesApiModule',
'ResponsePoliciesApiModule',
'RTRApiModule',
'MODULE_FILTER_ATTRIBUTES',
]

from caracara.modules.flight_control import FlightControlApiModule
from caracara.modules.hosts import (
FILTER_ATTRIBUTES as hosts_filter_attributes,
HostsApiModule,
Expand Down
6 changes: 6 additions & 0 deletions caracara/modules/flight_control/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Caracara FlightControlApiModule."""
__all__ = [
'FlightControlApiModule',
]

from caracara.modules.flight_control.flight_control import FlightControlApiModule
94 changes: 94 additions & 0 deletions caracara/modules/flight_control/flight_control.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""Falcon Flight Control (MSSP) APIs.
This module handles interaction with Parent CIDs, which have beneath them children (members) that
can be interfaced with directly.
This module handles interactions with the Parent CID's management APIs. To authenticate to
a child/member CID, use the member_cid kwarg when initialising a Caracara Client object.
"""
from typing import (
Dict,
List,
Union,
)

from falconpy import (
FlightControl,
OAuth2,
)

from caracara.common.batching import batch_get_data
from caracara.common.module import FalconApiModule
from caracara.common.pagination import all_pages_numbered_offset_parallel


class FlightControlApiModule(FalconApiModule):
"""The FlightControlApiModule facilitates interactions with the Flight Control (MSSP) API."""

name = "CrowdStrike Falcon Flight Control API Module"
help = "Interact with the management API calls in a Falcon Flight Control (MSSP) Parent CID"

def __init__(self, api_authentication: OAuth2):
"""Construct an instance of the FlightControlApiModule class."""
super().__init__(api_authentication)

self.logger.debug("Configuring the FalconPy Flight Control API")
self.flight_control_api = FlightControl(auth_object=self.api_authentication)

def get_child_cids(self) -> List[str]:
"""Retreives a list of every Child/Member CID within a Parent instance.
This function will return a list of CID strings without additional data. To get the names
of the CIDs, either pass the results of this function into get_child_cid_data(), or use the
describe_child_cids() function to obtain all this data in one function call.
Returns
-------
list: A list of all Child CIDs owned by the Parent CID associated with this Caracara Client
instance
"""
self.logger.info("Obtaining a list of all Child CIDs")
child_cids: List[str] = all_pages_numbered_offset_parallel(
self.flight_control_api.query_children,
self.logger,
10,
)
return child_cids

def get_child_cid_data(self, cids: List[str]) -> Dict[str, Dict[str, Union[List[str], str]]]:
"""Return a dictionary containing details for every Child CID specified by ID.
You should use this endpoint if you have a list of Child CIDs associated with the Parent
CID you are authenticated to within this Caracara Client instance. If you do not yet have
a list of Child CIDs, either use the get_child_cids() function to obtain these first,
or alternatively use the describe_child_cids() function to obtain all this data in one
function call.
Arguments
---------
cids: [str], required
A list of Falcon Customer IDs (CIDs) associated with this Parent Falcon tenant
Returns
-------
dict: A dictionary containing details for every Child CID listed.
"""
self.logger.info("Obtaining data for %d child CIDs", len(cids))
child_cid_data: Dict[str, Dict[str, Union[List[str], str]]] = batch_get_data(
cids,
self.flight_control_api.get_children,
)
return child_cid_data

def describe_child_cids(self) -> Dict[str, Dict[str, Union[List[str], str]]]:
"""Return a dictionary containing details for each Child CID associated with this tenant.
Returns
-------
dict: A dictionary containing details for every Child CID associated with this
Parent Falcon tenant (CID)
"""
self.logger.info("Describing this Parent CID's Child CIDs")
child_cids = self.get_child_cids()
child_cid_data = self.get_child_cid_data(cids=child_cids)
return child_cid_data
24 changes: 24 additions & 0 deletions examples/flight_control/describe_child_cids.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python3
"""
Caracara Examples Collection.
describe_child_cids.py
This example will show all Child CIDs within a Parent Falcon Flight Control / MSSP CID.
"""
from caracara import Client

from examples.common import caracara_example, pretty_print


@caracara_example
def describe_child_cids(**kwargs):
"""Dump out every child Falcon tenant to screen when authenticated to a Parent CID."""
client: Client = kwargs['client']

child_cids = client.flight_control.describe_child_cids()
print(pretty_print(child_cids))


if __name__ == "__main__":
describe_child_cids()
Loading

0 comments on commit fce2e0b

Please sign in to comment.