-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds maintenance token retrieval (#156)
- Loading branch information
1 parent
c7da194
commit 7d8ea0f
Showing
9 changed files
with
418 additions
and
225 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"""Caracara Sensor Policies API Module.""" | ||
__all__ = [ | ||
'SensorUpdatePoliciesApiModule', | ||
] | ||
|
||
from caracara.modules.sensor_update_policies.sensor_update_policies \ | ||
import SensorUpdatePoliciesApiModule |
87 changes: 87 additions & 0 deletions
87
caracara/modules/sensor_update_policies/sensor_update_policies.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
"""Sensor Update Policy APIs. | ||
This module allows for interaction with the Sensor Update policies, and facilitates | ||
the retrieval of maintenance tokens. | ||
""" | ||
import datetime | ||
|
||
from typing import Optional | ||
|
||
from falconpy import ( | ||
OAuth2, | ||
SensorUpdatePolicies, | ||
) | ||
|
||
from caracara.common.exceptions import BaseCaracaraError | ||
from caracara.common.module import FalconApiModule | ||
|
||
|
||
class SensorUpdatePoliciesApiModule(FalconApiModule): | ||
"""This module facilitates interactions with the Sensor Update Policies API.""" | ||
|
||
name = "CrowdStrike Sensor Update Policies API Module" | ||
help = "Interact with the Sensor Update Policies API, and get maintenance tokens" | ||
|
||
def __init__(self, api_authentication: OAuth2): | ||
"""Construct an instance of the SensorUpdatePoliciesApiModule.""" | ||
super().__init__(api_authentication) | ||
|
||
self.logger.debug("Configuring the FalconPy Sensor Update Policies module") | ||
self.sensor_update_policies_api = SensorUpdatePolicies(auth_object=self.api_authentication) | ||
|
||
def get_maintenance_token( | ||
self, | ||
device_id: str, | ||
audit_message: Optional[str] = None, | ||
) -> str: | ||
"""Get the maintenance token for a device. | ||
Arguments | ||
--------- | ||
device_id: str, required | ||
A Falcon Device ID (AID) to get the maintenance token for. | ||
audit_message: str or None | ||
A text string containing an audit message for the retrieval of the maintenance token. | ||
If left blank / None, Caracara will generate one for you. | ||
Returns | ||
------- | ||
str: The maintenance token. | ||
""" | ||
if audit_message is None: | ||
timestamp = datetime.datetime.now(tz=datetime.timezone.utc,).strftime( | ||
"%Y-%m-%d %H:%M:%S" | ||
) | ||
|
||
audit_message = f"Generated via Caracara at {timestamp} UTC" | ||
|
||
response = self.sensor_update_policies_api.reveal_uninstall_token( | ||
audit_message=audit_message, | ||
device_id=device_id, | ||
) | ||
|
||
if response['status_code'] == 200: | ||
body = response['body'] | ||
return body['resources'][0]['uninstall_token'] | ||
|
||
raise BaseCaracaraError( | ||
"The API operation failed to generate a maintenance token." | ||
"Check that you have the Sensor Update Policies - Write permission " | ||
"enabled on your API token." | ||
) | ||
|
||
def get_bulk_maintenance_token(self, audit_message: Optional[str] = None) -> str: | ||
"""Get the bulk maintenance token for a Falcon tenant. | ||
Arguments | ||
--------- | ||
audit_message: str or None | ||
A text string containing an audit message for the retrieval of the maintenance token. | ||
If left blank / None, Caracara will generate one for you. | ||
Returns | ||
------- | ||
str: The bulk maintenance token. | ||
""" | ||
return self.get_maintenance_token(device_id="MAINTENANCE", audit_message=audit_message) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
""" | ||
Caracara Example Collection. | ||
This file contains a pretty prompt_toolkit-based completer for devices. | ||
""" | ||
from typing import Dict, Iterable | ||
|
||
from prompt_toolkit import prompt | ||
from prompt_toolkit.completion import CompleteEvent, Completer, Completion | ||
from prompt_toolkit.document import Document | ||
|
||
|
||
class PrettyCompleter(Completer): | ||
"""Prompt Toolkit Completer that provides a searchable list of items.""" | ||
|
||
def __init__(self, data_dict: Dict[str, Dict]): | ||
"""Create a new completer based on a dictionary that maps items to meta strings. | ||
Each item should be in the format: | ||
{ | ||
"id1": "label", | ||
"id2": "label2", | ||
etc. | ||
} | ||
""" | ||
self.data_dict = data_dict | ||
|
||
def get_completions( | ||
self, | ||
document: Document, | ||
complete_event: CompleteEvent, | ||
) -> Iterable[Completion]: | ||
"""Yield items that match the entered search string.""" | ||
for item_id, item_label in self.data_dict.items(): | ||
word_lower = document.current_line.lower() | ||
if word_lower in item_id.lower() or word_lower in item_label.lower(): | ||
yield Completion( | ||
item_id, | ||
start_position=-len(document.current_line), | ||
display=item_id, | ||
display_meta=item_label, | ||
) | ||
|
||
|
||
def choose_item(items: Dict[str, Dict], prompt_text="Item Search") -> str: | ||
"""Visually choose an item ID from a dict of IDs mapped to strings.""" | ||
completer = PrettyCompleter(data_dict=items) | ||
chosen_id = None | ||
while chosen_id not in items: | ||
chosen_id = prompt(f"{prompt_text} >", completer=completer) | ||
|
||
print(chosen_id) | ||
return chosen_id |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#!/usr/bin/env python3 | ||
""" | ||
Caracara Examples Collection. | ||
get_maintenance_token.py | ||
This example will allow you to search for a system in the CID and get its maintenance token. | ||
""" | ||
from typing import Dict | ||
|
||
from caracara import Client | ||
|
||
from examples.common import ( | ||
caracara_example, | ||
choose_item, | ||
) | ||
|
||
|
||
@caracara_example | ||
def get_maintenance_token(**kwargs): | ||
"""Search for a system and get its maintenance token.""" | ||
client: Client = kwargs['client'] | ||
|
||
print("Getting all devices in the Falcon tenant") | ||
devices: Dict[str, Dict] = client.hosts.describe_devices() | ||
|
||
id_name_mapping = { | ||
"MAINTENANCE": "Bulk Maintenance Token", | ||
} | ||
for device_id, device_data in devices.items(): | ||
id_name_mapping[device_id] = device_data['hostname'] | ||
|
||
chosen_id = choose_item(id_name_mapping, prompt_text="Search for a Device") | ||
|
||
maintenance_token = client.sensor_update_policies.get_maintenance_token(chosen_id) | ||
print(maintenance_token) |
Oops, something went wrong.