Skip to content

Commit

Permalink
Update all integrations
Browse files Browse the repository at this point in the history
  • Loading branch information
topher-lo committed Jan 24, 2025
1 parent ff88c17 commit 41fa1a3
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 66 deletions.
5 changes: 3 additions & 2 deletions registry/tracecat_registry/integrations/ansible.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ async def run_playbook(
list[dict[str, Any]], Field(..., description="List of plays to run")
],
extra_vars: Annotated[
dict[str, Any],
dict[str, Any] | None,
Field(description="Extra variables to pass to the playbook"),
] = None,
runner_kwargs: Annotated[
dict[str, Any],
dict[str, Any] | None,
Field(description="Additional keyword arguments to pass to the Ansible runner"),
] = None,
) -> list[dict[str, Any]]:
Expand All @@ -59,6 +59,7 @@ async def run_playbook(
"Either `ANSIBLE_SSH_KEY` or `ANSIBLE_PASSWORDS` must be provided"
)

extra_vars = extra_vars or {}
runner_kwargs = runner_kwargs or {}

with tempfile.TemporaryDirectory() as temp_dir:
Expand Down
6 changes: 3 additions & 3 deletions registry/tracecat_registry/integrations/aws_boto3.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"AWS_ROLE_SESSION_NAME",
],
)
"""AWS secret.
"""AWS credentials.
- name: `aws`
- optional_keys:
Expand Down Expand Up @@ -102,7 +102,7 @@ async def call_api(
),
],
params: Annotated[
dict[str, Any],
dict[str, Any] | None,
Field(..., description="Parameters for the API method."),
] = None,
) -> dict[str, Any]:
Expand Down Expand Up @@ -137,7 +137,7 @@ async def call_paginated_api(
),
],
params: Annotated[
dict[str, Any],
dict[str, Any] | None,
Field(..., description="Parameters for the API paginator."),
] = None,
) -> list[dict[str, Any]]:
Expand Down
18 changes: 10 additions & 8 deletions registry/tracecat_registry/integrations/aws_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
BUCKET_REGEX = re.compile(r"^[a-z0-9][a-z0-9.-]*[a-z0-9]$")

s3_secret = RegistrySecret(
name="s3",
name="aws_s3",
optional_keys=[
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
Expand All @@ -22,11 +22,9 @@
"AWS_ROLE_SESSION_NAME",
],
)
"""AWS secret.
"""AWS credentials.
Secret
------
- name: `aws`
- name: `aws_s3`
- optional_keys:
Either:
- `AWS_ACCESS_KEY_ID`
Expand All @@ -42,9 +40,11 @@

@registry.register(
default_title="Parse S3 URI",
description="Parse an S3 URI into a bucket and key.",
description="Parse an S3 URI into bucket name and object key.",
display_group="AWS S3",
doc_url="https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-example-download-file.html",
namespace="integrations.aws_s3",
secrets=[s3_secret],
)
async def parse_uri(uri: str) -> tuple[str, str]:
uri = str(uri).strip()
Expand All @@ -60,9 +60,10 @@ async def parse_uri(uri: str) -> tuple[str, str]:


@registry.register(
default_title="Download S3 Object",
default_title="Get S3 object",
description="Download an object from S3 and return its body as a string.",
display_group="AWS S3",
doc_url="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html#S3.Client.get_object",
namespace="integrations.aws_s3",
secrets=[s3_secret],
)
Expand All @@ -77,4 +78,5 @@ async def download_object(
# Defensively handle different types of bodies
if isinstance(body, bytes):
return body.decode("utf-8")
return body
else:
raise ValueError(f"Unexpected body type. Expected bytes, got {type(body)}")
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@


@registry.register(
default_title="Get auth token",
default_title="Get access token",
description="Retrieve a JWT token for Check Point Infinity API calls.",
display_group="Check Point Infinity",
doc_url="https://app.swaggerhub.com/apis-docs/Check-Point/infinity-portal-api/1.0.6#/User%20Control/post_auth_external",
namespace="integrations.check_point_infinity",
secrets=[check_point_infinity_secret],
)
async def get_auth_token(
async def get_access_token(
base_url: str = "https://cloudinfra-gw-us.portal.checkpoint.com",
) -> str:
async with httpx.AsyncClient() as client:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
@registry.register(
default_title="Call Crowdstrike API",
description="Instantiate a FalconPy Uber Class client and call a Crowdstrike API method.",
display_group="Crowdstrike FalconPy",
display_group="Crowdstrike",
doc_url="https://falconpy.io/Usage/Basic-Uber-Class-usage.html",
namespace="integrations.crowdstrike_falconpy",
namespace="integrations.crowdstrike",
secrets=[crowdstrike_secret],
)
async def call_command(
Expand All @@ -37,7 +37,7 @@ async def call_command(
),
],
params: Annotated[
dict[str, Any],
dict[str, Any] | None,
Field(..., description="Parameters to pass into the command"),
] = None,
member_cid: Annotated[
Expand Down
21 changes: 16 additions & 5 deletions registry/tracecat_registry/integrations/google_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,33 @@


@registry.register(
default_title="Get auth token",
description="Given service account credentials as a JSON string, retrieves a JWT token for Google API calls.",
default_title="Get access token",
description="Given service account credentials as a JSON string, retrieve a JWT token for Google API calls.",
display_group="Google API",
doc_url="https://googleapis.dev/python/google-auth/latest/reference/google.oauth2.service_account.html#google.oauth2.service_account.Credentials.from_service_account_info",
namespace="integrations.google_api",
secrets=[google_api_secret],
)
def get_auth_token(
scopes: Annotated[list[str], Field(..., description="Google API scopes.")],
subject: Annotated[str, Field(..., description="Google API subject.")] = None,
def get_access_token(
scopes: Annotated[
list[str] | None,
Field(
...,
description='Google API scopes, defaults to ["https://www.googleapis.com/auth/cloud-platform"].',
),
] = None,
subject: Annotated[
str | None,
Field(..., description="Google API subject."),
] = None,
) -> str:
creds_json = secrets.get("GOOGLE_API_CREDENTIALS")
try:
creds = orjson.loads(creds_json)
except orjson.JSONDecodeError as e:
raise ValueError("`GOOGLE_API_CREDENTIALS` is not a valid JSON string.") from e

scopes = scopes or ["https://www.googleapis.com/auth/cloud-platform"]
credentials = service_account.Credentials.from_service_account_info(
creds,
scopes=scopes,
Expand Down
4 changes: 2 additions & 2 deletions registry/tracecat_registry/integrations/jamf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@


@registry.register(
default_title="Get auth token",
default_title="Get access token",
description="Retrieve a bearer token for Jamf Pro API calls.",
display_group="Jamf",
doc_url="https://developer.jamf.com/jamf-pro/docs/jamf-pro-api-overview#authentication-and-authorization",
namespace="integrations.jamf",
secrets=[jamf_secret],
)
async def get_auth_token(base_url: str) -> str:
async def get_access_token(base_url: str) -> str:
async with httpx.AsyncClient() as client:
response = await client.post(
f"{base_url}/api/oauth/token",
Expand Down
10 changes: 5 additions & 5 deletions registry/tracecat_registry/integrations/microsoft_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,30 @@


@registry.register(
default_title="Get auth token",
default_title="Get access token",
description="Retrieve a JWT token for Microsoft Graph API calls from a confidential application.",
display_group="Microsoft Graph",
doc_url="https://msal-python.readthedocs.io/en/latest/#confidentialclientapplication",
namespace="integrations.microsoft_graph",
secrets=[microsoft_graph_secret],
)
def get_auth_token(
def get_access_token(
scopes: Annotated[
list[str],
list[str] | None,
Field(
...,
description='Microsoft Graph scopes, defaults to ["https://graph.microsoft.com/.default"].',
),
] = None,
authority: Annotated[
str,
str | None,
Field(
...,
description='Microsoft Graph authority, defaults to "https://login.microsoftonline.com/common".',
),
] = None,
oidc_authority: Annotated[
str,
str | None,
Field(
...,
description='Microsoft Graph OIDC authority, defaults to "https://login.microsoftonline.com/common".',
Expand Down
30 changes: 18 additions & 12 deletions registry/tracecat_registry/integrations/pymongo.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
keys=["MONGODB_CONNECTION_STRING"],
)

"""MongoDB Secret.
"""MongoDB connection string.
- name: `mongodb`
- key:
Expand All @@ -22,39 +22,45 @@


@registry.register(
default_title="Perform MongoDB CRUD",
description="Performs a MongoDB operation on a specified collection.",
default_title="Execute database operation",
description="Instantiate a PyMongo client and execute an operation on a Collection object.",
display_group="MongoDB",
doc_url="https://pymongo.readthedocs.io/en/stable/api/pymongo/asynchronous/collection.html",
namespace="integrations.mongodb",
secrets=[mongodb_secret],
)
async def perform_mongodb_crud(
operation: Annotated[
async def execute_operation(
operation_name: Annotated[
str,
Field(
...,
description="Operation to perform on the MongoDB Collection, e.g. 'find', 'insert_one'.",
description="Operation to perform on the Collection, e.g. 'find', 'insert_one'.",
),
],
database_name: Annotated[
str,
Field(..., description="The name of the target database."),
Field(..., description="Database to operate on"),
],
collection_name: Annotated[
str,
Field(..., description="The name of the target collection"),
Field(..., description="Collection to operate on"),
],
params: Annotated[
dict[str, Any],
Field(..., description="Parameters for the operation."),
dict[str, Any] | None,
Field(..., description="Parameters for the operation"),
] = None,
) -> dict[str, Any] | list[dict[str, Any]]:
params = params or {}
# Connect to MongoDB
connection_string = secrets.get("MONGODB_CONNECTION_STRING")
client = MongoClient(connection_string)

# Get the database and collection
db = client[database_name]
collection = db[collection_name]
result = getattr(collection, operation)(**params)

# Call the operation
params = params or {}
result = getattr(collection, operation_name)(**params)

if isinstance(result, Cursor):
# Stringify the ObjectIDs
Expand Down
33 changes: 20 additions & 13 deletions registry/tracecat_registry/integrations/slack_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from tracecat_registry import RegistrySecret, registry, secrets

slack_secret = RegistrySecret(name="slack", keys=["SLACK_BOT_TOKEN"])
"""Slack secret.
"""Slack bot token.
- name: `slack`
- keys:
Expand All @@ -18,58 +18,65 @@

@registry.register(
default_title="Call Slack API",
description="Call any Slack API using the Slack Python SDK",
description="Instantiate a Slack client and call an API method.",
display_group="Slack",
doc_url="https://api.slack.com/methods",
namespace="integrations.slack",
secrets=[slack_secret],
)
async def call_slack_api(
async def call_api(
sdk_method: Annotated[
str,
Field(
..., description="Slack Python SDK method name (e.g. `chat_postMessage`)"
...,
description="Slack Python SDK method name (e.g. `chat_postMessage`)",
),
],
params: Annotated[
dict, Field(..., description="Slack Python SDK method parameters")
],
dict[str, Any] | None,
Field(..., description="Slack Python SDK method parameters"),
] = None,
) -> dict[str, Any]:
bot_token = secrets.get("SLACK_BOT_TOKEN")
client = AsyncWebClient(token=bot_token)
params = params or {}
result = await getattr(client, sdk_method)(**params)
return result


@registry.register(
default_title="Call Paginated Slack API",
description="Call any Slack API that supports cursor / pagination using the Slack Python SDK and retrieve all items",
default_title="Call paginated Slack API",
description="Instantiate a Slack client and call a paginated API method.",
display_group="Slack",
doc_url="https://api.slack.com/methods",
namespace="integrations.slack",
secrets=[slack_secret],
)
async def call_paginated_slack_api(
async def call_paginated_api(
sdk_method: Annotated[
str,
Field(
...,
description="Slack Python SDK method name that supports cursor / pagination (e.g. `conversations_history`)",
description="Slack Python SDK method name that supports cursor pagination (e.g. `conversations_history`)",
),
],
params: Annotated[
dict, Field(..., description="Slack Python SDK method parameters")
],
dict[str, Any] | None,
Field(..., description="Slack Python SDK method parameters"),
] = None,
limit: Annotated[
int,
Field(
...,
description="Maximum number of items to retrieve. Must be less than 1000",
),
] = 200,
) -> dict[str, Any]:
) -> list[dict[str, Any]]:
bot_token = secrets.get("SLACK_BOT_TOKEN")
client = AsyncWebClient(token=bot_token)
cursor = None
items = []
params = params or {}
while True:
result = await getattr(client, sdk_method)(**params, cursor=cursor, limit=limit)
items.extend(result["items"])
Expand Down
4 changes: 2 additions & 2 deletions registry/tracecat_registry/integrations/tenable_nessus.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

@registry.register(
default_title="Call Nessus API",
description="Call any Nessus API using the pyTenable library",
display_group="Tenabl Nessus",
description="Instantiate a pyTenable Nessus client and call a Nessus API method.",
display_group="Tenable Nessus",
doc_url="https://pytenable.readthedocs.io/en/stable/api/nessus/index.html",
namespace="integrations.tenable_nessus",
secrets=[tenable_secret],
Expand Down
Loading

0 comments on commit 41fa1a3

Please sign in to comment.