Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formats codebase using black and bumps requirements #146

Merged
merged 5 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[flake8]
max-line-length = 100
extend-ignore = E203
2 changes: 2 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ jobs:
- name: Lint package docstrings and comments with pydocstyle
if: success() || failure()
run: poetry run pydocstyle falcon_toolkit/
- name: Lint package with black
run: poetry run black -l 100 --check falcon_toolkit/
3 changes: 2 additions & 1 deletion falcon_toolkit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

A CLI for CrowdStrike Falcon, made with love by the CrowdStrike Services Team.
"""

__all__ = [
'__version__',
"__version__",
]

from falcon_toolkit.common.meta import __version__
1 change: 1 addition & 0 deletions falcon_toolkit/common/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
hold a FalconPy authentication object. It will be possible to generate more of these backends for
other purposes, such as for authentication against alternative API gateways.
"""

from __future__ import annotations
from abc import (
abstractmethod,
Expand Down
1 change: 1 addition & 0 deletions falcon_toolkit/common/auth_backends/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

This file configures the default authentication backends.
"""

from falcon_toolkit.common.auth_backends.public_mssp import PublicCloudFlightControlParentCIDBackend
from falcon_toolkit.common.auth_backends.public_single_cid import PublicCloudSingleCIDBackend

Expand Down
22 changes: 10 additions & 12 deletions falcon_toolkit/common/auth_backends/public_mssp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This authentication backend can take public cloud API keys (US-1, US-2, EU-1), and will ask the
user which child CID to authenticate against.
"""

import os

from typing import Dict, Optional
Expand Down Expand Up @@ -93,10 +94,10 @@ def dump_config(self) -> Dict[str, object]:
keyring.
"""
config: Dict[str, object] = {}
config['client_id']: str = self.client_id
config['cloud_name']: str = self.cloud_name
config['ssl_verify']: bool = self.ssl_verify
config['proxy']: Dict[str, str] = self.proxy
config["client_id"]: str = self.client_id
config["cloud_name"]: str = self.cloud_name
config["ssl_verify"]: bool = self.ssl_verify
config["proxy"]: Dict[str, str] = self.proxy

return config

Expand All @@ -112,18 +113,15 @@ def authenticate(self) -> Client:
child_cids = parent_client.flight_control.get_child_cids()
chosen_cid_str = os.environ.get("FALCON_MSSP_CHILD_CID")
if chosen_cid_str and chosen_cid_str.lower() in child_cids:
chosen_cid = parent_client.flight_control.get_child_cid_data(
cids=[chosen_cid_str]
)[chosen_cid_str]
chosen_cid = parent_client.flight_control.get_child_cid_data(cids=[chosen_cid_str])[
chosen_cid_str
]
else:
child_cids_data = parent_client.flight_control.get_child_cid_data(cids=child_cids)
chosen_cid_str = choose_cid(
cids=child_cids_data,
prompt_text="MSSP Child CID Search"
)
chosen_cid_str = choose_cid(cids=child_cids_data, prompt_text="MSSP Child CID Search")
chosen_cid = child_cids_data[chosen_cid_str]

chosen_cid_name = chosen_cid['name']
chosen_cid_name = chosen_cid["name"]
print(f"Connecting to {chosen_cid_name}")

client = Client(
Expand Down
9 changes: 5 additions & 4 deletions falcon_toolkit/common/auth_backends/public_single_cid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This authentication backend can take public cloud API keys (US-1, US-2, EU-1), and will return
an OAuth2 object suitable for authenticating with FalconPy.
"""

from typing import Dict, Optional

import keyring
Expand Down Expand Up @@ -81,10 +82,10 @@ def dump_config(self) -> Dict[str, object]:
keyring.
"""
config: Dict[str, object] = {}
config['client_id'] = self.client_id
config['cloud_name'] = self.cloud_name
config['ssl_verify'] = self.ssl_verify
config['proxy'] = self.proxy
config["client_id"] = self.client_id
config["cloud_name"] = self.cloud_name
config["ssl_verify"] = self.ssl_verify
config["proxy"] = self.proxy

return config

Expand Down
7 changes: 4 additions & 3 deletions falcon_toolkit/common/auth_backends/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- A cloud selection function to allow a user to choose a cloud via Prompt Toolkit
- Advanced options configuration for overriding cloud, TLS validation, etc.
"""

from typing import (
Dict,
List,
Expand Down Expand Up @@ -56,8 +57,8 @@ class AdvancedOptionsType(NamedTuple):
def advanced_options_wizard() -> AdvancedOptionsType:
"""Define advanced connection options and return an AdvancedOptionsType."""
advanced_options_input = fancy_input("Do you want to configure more options? [y/n]: ")
if advanced_options_input not in ('y', 'Y'):
return AdvancedOptionsType('auto', True, None)
if advanced_options_input not in ("y", "Y"):
return AdvancedOptionsType("auto", True, None)

cloud_name = cloud_choice()

Expand All @@ -76,7 +77,7 @@ def advanced_options_wizard() -> AdvancedOptionsType:
proxy_url_input = fancy_input("HTTPS proxy URL (leave blank if not needed): ", loop=False)

if proxy_url_input:
proxy_dict = {'https', proxy_url_input}
proxy_dict = {"https", proxy_url_input}

advanced_options_result = AdvancedOptionsType(cloud_name, ssl_verify, proxy_dict)
return advanced_options_result
27 changes: 15 additions & 12 deletions falcon_toolkit/common/cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Falcon Toolkit: Common CLI Functions."""

import sys

from typing import List
Expand All @@ -13,39 +14,41 @@

def get_instance(ctx: click.Context):
"""Load a specified Falcon instance configuration ready for use."""
config: FalconToolkitConfig = ctx.obj['config']
profile_name: str = ctx.obj['profile_name']
config: FalconToolkitConfig = ctx.obj["config"]
profile_name: str = ctx.obj["profile_name"]

if profile_name in config.instances:
profile = config.instances[profile_name]
elif not profile_name and len(config.instances) == 1:
profile = list(config.instances.values())[0]
elif not config.instances:
click.echo(click.style("No profiles are configured. Please set one up first.", fg='red'))
click.echo(click.style("No profiles are configured. Please set one up first.", fg="red"))
sys.exit(1)
elif not profile_name:
click.echo(click.style(
"Multiple profiles are configured, so you must use the -p/--profile option "
"to choose a profile to execute this tool with.",
fg='red',
))
click.echo(
click.style(
"Multiple profiles are configured, so you must use the -p/--profile option "
"to choose a profile to execute this tool with.",
fg="red",
)
)
sys.exit(1)
else:
click.echo(click.style(f"The profile {profile_name} does not exist.", fg='red'))
click.echo(click.style(f"The profile {profile_name} does not exist.", fg="red"))
sys.exit(1)

return profile


def parse_cli_filters(filter_kv_strings: List[str], client: Client) -> FalconFilter:
"""Parse consecutive chains of -f filters into a FalconFilter object for later use."""
filters = client.FalconFilter(dialect='hosts')
filters = client.FalconFilter(dialect="hosts")
for filter_kv_string in filter_kv_strings:
if '=' not in filter_kv_string:
if "=" not in filter_kv_string:
raise ValueError("Filter key=value string is in the wrong format")
first_equals = filter_kv_string.index("=")
filter_key = filter_kv_string[0:first_equals]
filter_value = filter_kv_string[first_equals + 1:]
filter_value = filter_kv_string[first_equals + 1 :]
filters.create_new_filter_from_kv_string(filter_key, filter_value)

return filters
11 changes: 5 additions & 6 deletions falcon_toolkit/common/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
These configurations are stored in a wider config file stored within the configuration
path (usually ~/FalconToolkit/FalconToolkit.json).
"""

from __future__ import annotations
import importlib.util
import json
Expand Down Expand Up @@ -63,9 +64,7 @@ def load_config(self, config: Dict[str, object]):
break

if not matching_auth_backend:
raise ValueError(
f"Auth backend {auth_backend_name} is not loaded or does not exist"
)
raise ValueError(f"Auth backend {auth_backend_name} is not loaded or does not exist")

auth_backend_config = auth.get("backend_config")
if not auth_backend_config:
Expand All @@ -81,7 +80,7 @@ def dump_config(self):
"auth": {
"backend_name": self.auth_backend.simple_name,
"backend_config": self.auth_backend.dump_config(),
}
},
}


Expand Down Expand Up @@ -113,7 +112,7 @@ def __init__(self, config_path: str):
"""Load a Falcon Toolkit configuration file from disk."""
self.config_file_path = os.path.join(config_path, CONFIG_FILENAME)
if os.path.exists(self.config_file_path):
with open(self.config_file_path, 'rb') as config_file_handle:
with open(self.config_file_path, "rb") as config_file_handle:
config_data = json.load(config_file_handle)
else:
config_data = {}
Expand All @@ -139,7 +138,7 @@ def write_config(self):
"auth_backends": self.additional_auth_backend_paths,
"instances": [x.dump_config() for x in list(self.instances.values())],
}
with open(self.config_file_path, 'w', encoding='utf8') as config_file_handle:
with open(self.config_file_path, "w", encoding="utf8") as config_file_handle:
json.dump(config_data, config_file_handle, sort_keys=True, indent=4)

def add_instance(self):
Expand Down
11 changes: 6 additions & 5 deletions falcon_toolkit/common/console_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
This file contains tools to help with displaying data on the console in a user-friendly,
colourful and/or helpful way.
"""

import platform


ESC = '\033'
OSC = ESC + ']'
ST = ESC + '\\'
ESC = "\033"
OSC = ESC + "]"
ST = ESC + "\\"


def build_hyperlink(target: str, text: str, link_id: str = None):
Expand All @@ -17,7 +18,7 @@ def build_hyperlink(target: str, text: str, link_id: str = None):
id_str = "id=" + link_id
else:
id_str = ""
return f'{OSC}8;{id_str};{target}{ST}{text}{OSC}8;;{ST}'
return f"{OSC}8;{id_str};{target}{ST}{text}{OSC}8;;{ST}"


def build_file_hyperlink(file_path: str, text: str, link_id: str = None):
Expand All @@ -27,7 +28,7 @@ def build_file_hyperlink(file_path: str, text: str, link_id: str = None):
else:
hostname = platform.node()

if file_path.startswith('/'):
if file_path.startswith("/"):
file_path = file_path[1:]

uri_file_path = f"file://{hostname}/{file_path}"
Expand Down
5 changes: 3 additions & 2 deletions falcon_toolkit/common/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Falcon Toolkit: Common Constants."""

import os

import platformdirs
Expand All @@ -16,6 +17,6 @@

# Logging
LOG_CONSOLE_FORMATTER = "%(message)s"
LOG_FILE_DATE_FORMAT = '%Y-%m-%dT%H:%M:%S%z'
LOG_FILE_OUTPUT_FORMAT = '%(asctime)s %(name)-24s %(levelname)-8s %(message)s'
LOG_FILE_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S%z"
LOG_FILE_OUTPUT_FORMAT = "%(asctime)s %(name)-24s %(levelname)-8s %(message)s"
LOG_SUB_DIR = "logs"
9 changes: 5 additions & 4 deletions falcon_toolkit/common/logging_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
capture logs from both the toolkit itself, as well as Caracara behind the scenes.
All logs are compressed using gzip to keep file sizes down.
"""

import datetime
import gzip
import logging
Expand Down Expand Up @@ -48,7 +49,7 @@ def configure_logger(
# Gzip compress the main log file on the fly via a memory stream.
# This is required to avoid the gzip file from being corrupted if the
# the script ends prematurely (e.g, it crashes).
log_output_file = gzip.open(log_filepath, mode='wt', encoding='utf-8')
log_output_file = gzip.open(log_filepath, mode="wt", encoding="utf-8")
stream_handler = logging.StreamHandler(log_output_file)
memory_handler = logging.handlers.MemoryHandler(
capacity=1024,
Expand All @@ -60,22 +61,22 @@ def configure_logger(
datefmt=LOG_FILE_DATE_FORMAT,
format=LOG_FILE_OUTPUT_FORMAT,
handlers=[memory_handler],
encoding='utf-8',
encoding="utf-8",
)
else:
logging.basicConfig(
level=log_level,
format=LOG_FILE_OUTPUT_FORMAT,
datefmt=LOG_FILE_DATE_FORMAT,
filename=log_filepath,
filemode='wt',
filemode="wt",
)

console = logging.StreamHandler()
console.setLevel(level=log_level)
console_formatter = logging.Formatter(LOG_CONSOLE_FORMATTER)
console.setFormatter(console_formatter)
logging.getLogger('').addHandler(console)
logging.getLogger("").addHandler(console)

logging.debug("Logger configured")
return log_filepath_base
4 changes: 1 addition & 3 deletions falcon_toolkit/common/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@
import pkg_resources

# Derive the version via pkg_resources, which is populated based on the version in pyproject.toml
__version__ = pkg_resources.get_distribution(
__name__.split(".", maxsplit=1)[0]
).version
__version__ = pkg_resources.get_distribution(__name__.split(".", maxsplit=1)[0]).version
4 changes: 1 addition & 3 deletions falcon_toolkit/common/namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@ def __getitem__(self, key):

def __setitem__(self, key, value):
"""Assign a key to a value in the namespace."""
self.__init__(
** {key: value}
)
self.__init__(**{key: value})

def __delitem__(self, key):
"""Delete an item from the namespace."""
Expand Down
8 changes: 4 additions & 4 deletions falcon_toolkit/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
This file is a catch-all for small code snippets that can be shared across the various sub-modules
of the application.
"""

import os

from typing import Dict, Iterable
Expand All @@ -21,8 +22,7 @@
def fancy_input(prompt_text: str, loop: bool = True):
"""Request user input (with colour). Optionally loop until the input is not blank."""
inputted = False
colour_prompt = Style.BRIGHT + Fore.BLUE + \
prompt_text + Fore.RESET + Style.RESET_ALL
colour_prompt = Style.BRIGHT + Fore.BLUE + prompt_text + Fore.RESET + Style.RESET_ALL

while not inputted:
data = input(colour_prompt)
Expand Down Expand Up @@ -62,11 +62,11 @@ def filename_safe_string(unsafe_string: str) -> str:
This function is heavily inspired by https://stackoverflow.com/a/7406369.
"""
safe_string = "".join(
[c for c in unsafe_string if c.isalpha() or c.isdigit() or c == ' ']
[c for c in unsafe_string if c.isalpha() or c.isdigit() or c == " "]
).rstrip()

# Replace spaces with underscores to match the general format of the log filename
clean_string = safe_string.replace(' ', '_')
clean_string = safe_string.replace(" ", "_")

return clean_string

Expand Down
Loading
Loading