Skip to content
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
12 changes: 6 additions & 6 deletions functions/hello/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError


func = FoundryFunction.instance()
func = Function.instance()


# Handler hello
@func.handler(method='POST', path='/hello')
def on_post(request: FoundryRequest) -> FoundryResponse:
def on_post(request: Request) -> Response:

#
# Replace the following example code with your handler code
Expand All @@ -17,14 +17,14 @@ def on_post(request: FoundryRequest) -> FoundryResponse:
if 'name' not in request.body:
# This example expects 'name' field in the request body and returns
# an error response (400 - Bad Request) if not provided by the caller
return FoundryResponse(
return Response(
code=400,
errors=[FoundryAPIError(code=400, message='missing name from request body')]
errors=[APIError(code=400, message='missing name from request body')]
)

# Demonstrates how to return a success response with JSON body
# Replace with your response and update the response_schema.json to match
return FoundryResponse(
return Response(
body={'greeting': f'Hello {request.body["name"]}! It is nice to see you.'},
code=200,
)
Expand Down
2 changes: 1 addition & 1 deletion functions/hello/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
8 changes: 4 additions & 4 deletions functions/hello/test_main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import unittest
from unittest.mock import patch

from falconfoundry import FoundryRequest
from crowdstrike.foundry.function import Request

def mock_handler(*args, **kwargs):
def identity(func):
Expand All @@ -10,7 +10,7 @@ def identity(func):

class FnTestCase(unittest.TestCase):
def setUp(self):
patcher = patch('falconfoundry.FoundryFunction.handler', new=mock_handler)
patcher = patch('crowdstrike.foundry.function.Function.handler', new=mock_handler)
self.addCleanup(patcher.stop)
self.handler_patch = patcher.start()

Expand All @@ -20,7 +20,7 @@ def setUp(self):

def test_on_post_success(self):
from main import on_post
request = FoundryRequest()
request = Request()
request.body = {
"name": "Test User"
}
Expand All @@ -31,7 +31,7 @@ def test_on_post_success(self):

def test_on_post_missing_name(self):
from main import on_post
request = FoundryRequest()
request = Request()

response = on_post(request)
self.assertEqual(response.code, 400)
Expand Down
16 changes: 8 additions & 8 deletions functions/host-details/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError
# Import service collection you'd like to use
from falconpy import Hosts


func = FoundryFunction.instance()
func = Function.instance()


@func.handler(method='POST', path='/host-details')
def on_post(request: FoundryRequest) -> FoundryResponse:
def on_post(request: Request) -> Response:
# Validate request
if 'host_id' not in request.body:
return FoundryResponse(
return Response(
code=400,
errors=[FoundryAPIError(code=400, message='missing host_id from request body')]
errors=[APIError(code=400, message='missing host_id from request body')]
)

host_id = request.body['host_id']
Expand All @@ -24,14 +24,14 @@ def on_post(request: FoundryRequest) -> FoundryResponse:
response = falcon.get_device_details(ids=host_id)

if response["status_code"] != 200:
return FoundryResponse(
return Response(
code=response["status_code"],
errors=[FoundryAPIError(code=response["status_code"],
errors=[APIError(code=response["status_code"],
message=f"Error retrieving host: {response['body']}")],
)

# Return host information
return FoundryResponse(
return Response(
body={"host_details": response["body"]["resources"][0]},
code=200,
)
Expand Down
2 changes: 1 addition & 1 deletion functions/host-details/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
crowdstrike-falconpy
10 changes: 5 additions & 5 deletions functions/host-info/main.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError
from utils import validate_host_id, format_error_response
from logging import Logger
from typing import Dict


func = FoundryFunction.instance()
func = Function.instance()

# Handler on_post
@func.handler(method='POST', path='/host-info')
def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: Logger) -> FoundryResponse:
def on_post(request: Request, config: Dict[str, object] | None, logger: Logger) -> Response:
host_id = request.body.get('host_id')

logger.info(f"Host ID: {host_id}")
logger.info(f"Is valid? {validate_host_id(host_id)}")

if not validate_host_id(host_id):
return FoundryResponse(errors=format_error_response("Invalid host ID format"))
return Response(errors=format_error_response("Invalid host ID format"))

return FoundryResponse(
return Response(
code=200,
body={
"host":host_id
Expand Down
2 changes: 1 addition & 1 deletion functions/host-info/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
4 changes: 2 additions & 2 deletions functions/host-info/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import json
from typing import Dict, Any, Optional, Union, List
from falconfoundry import FoundryAPIError
from crowdstrike.foundry.function import APIError

def validate_host_id(host_id: str) -> bool:
"""Validate that a host ID is in the correct format."""
Expand All @@ -16,7 +16,7 @@ def validate_email(email: str) -> bool:

def format_error_response(message: str, code: int = 400) -> list[Any]:
"""Create a standardized error response."""
return [FoundryAPIError(code=code, message=message)]
return [APIError(code=code, message=message)]

def safe_json_parse(data: str) -> Optional[Dict[str, Any]]:
"""Safely parse JSON data."""
Expand Down
20 changes: 10 additions & 10 deletions functions/log-event/main.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError
from falconpy import APIHarnessV2
import time
import os
import uuid

func = FoundryFunction.instance()
func = Function.instance()


@func.handler(method='POST', path='/log-event')
def on_post(request: FoundryRequest) -> FoundryResponse:
def on_post(request: Request) -> Response:
# Validate request
if 'event_data' not in request.body:
return FoundryResponse(
return Response(
code=400,
errors=[FoundryAPIError(code=400, message='missing event_data')]
errors=[APIError(code=400, message='missing event_data')]
)

event_data = request.body['event_data']
Expand Down Expand Up @@ -47,9 +47,9 @@ def on_post(request: FoundryRequest) -> FoundryResponse:

if response["status_code"] != 200:
error_message = response.get('error', {}).get('message', 'Unknown error')
return FoundryResponse(
return Response(
code=response["status_code"],
errors=[FoundryAPIError(
errors=[APIError(
code=response["status_code"],
message=f"Failed to store event: {error_message}"
)]
Expand All @@ -63,17 +63,17 @@ def on_post(request: FoundryRequest) -> FoundryResponse:
headers=headers
)

return FoundryResponse(
return Response(
body={
"stored": True,
"metadata": query_response.get("body").get("resources", [])
},
code=200
)
except Exception as e:
return FoundryResponse(
return Response(
code=500,
errors=[FoundryAPIError(code=500, message=f"Error saving collection: {str(e)}")]
errors=[APIError(code=500, message=f"Error saving collection: {str(e)}")]
)


Expand Down
2 changes: 1 addition & 1 deletion functions/log-event/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
crowdstrike-falconpy
20 changes: 10 additions & 10 deletions functions/servicenow/main.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError
from falconpy import APIIntegrations
from logging import Logger
from typing import Dict


func = FoundryFunction.instance()
func = Function.instance()

@func.handler(method='POST', path='/ticket')
def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: Logger) -> FoundryResponse:
def on_post(request: Request, config: Dict[str, object] | None, logger: Logger) -> Response:
"""
Create an incident ticket in ServiceNow using the Table API.

Expand All @@ -25,9 +25,9 @@ def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: L
"""
# Validate required fields
if 'title' not in request.body or 'description' not in request.body:
return FoundryResponse(
return Response(
code=400,
errors=[FoundryAPIError(code=400, message='Missing required fields: title and description')]
errors=[APIError(code=400, message='Missing required fields: title and description')]
)

# Prepare payload for ServiceNow incident creation
Expand Down Expand Up @@ -76,9 +76,9 @@ def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: L

if response["status_code"] >= 400:
error_message = response.get('error', {}).get('message', 'Unknown error')
return FoundryResponse(
return Response(
code=response["status_code"],
errors=[FoundryAPIError(
errors=[APIError(
code=response["status_code"],
message=f"ServiceNow integration error: {error_message}"
)]
Expand All @@ -88,7 +88,7 @@ def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: L
result = response["body"]["result"]

# Return formatted response with incident details
return FoundryResponse(
return Response(
body={
"incident_id": result["sys_id"],
"incident_number": result["number"],
Expand All @@ -102,9 +102,9 @@ def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: L
)
except Exception as e:
logger.error(f"Error creating ServiceNow incident: {str(e)}", exc_info=True)
return FoundryResponse(
return Response(
code=500,
errors=[FoundryAPIError(code=500, message=f"Error creating incident: {str(e)}")]
errors=[APIError(code=500, message=f"Error creating incident: {str(e)}")]
)


Expand Down
2 changes: 1 addition & 1 deletion functions/servicenow/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
crowdstrike-falconpy
10 changes: 5 additions & 5 deletions functions/user-management/main.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
from falconfoundry import FoundryFunction, FoundryRequest, FoundryResponse, FoundryAPIError
from crowdstrike.foundry.function import Function, Request, Response, APIError
from utils import validate_email, format_error_response
from logging import Logger
from typing import Dict


func = FoundryFunction.instance()
func = Function.instance()

# Handler on_post
@func.handler(method='POST', path='/create-user')
def on_post(request: FoundryRequest, config: Dict[str, object] | None, logger: Logger) -> FoundryResponse:
def on_post(request: Request, config: Dict[str, object] | None, logger: Logger) -> Response:
email = request.body.get('email')

logger.info(f"Email: {email}")
logger.info(f"Is valid? {validate_email(email)}")

if not validate_email(email):
return FoundryResponse(errors=format_error_response("Invalid email format"))
return Response(errors=format_error_response("Invalid email format"))

return FoundryResponse(
return Response(
code=200,
body={
"email":email
Expand Down
2 changes: 1 addition & 1 deletion functions/user-management/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
crowdstrike-falcon-foundry==1.0.0
crowdstrike-foundry-function==1.1.1
4 changes: 2 additions & 2 deletions functions/user-management/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import re
import json
from typing import Dict, Any, Optional, Union, List
from falconfoundry import FoundryAPIError
from crowdstrike.foundry.function import APIError

def validate_host_id(host_id: str) -> bool:
"""Validate that a host ID is in the correct format."""
Expand All @@ -16,7 +16,7 @@ def validate_email(email: str) -> bool:

def format_error_response(message: str, code: int = 400) -> list[Any]:
"""Create a standardized error response."""
return [FoundryAPIError(code=code, message=message)]
return [APIError(code=code, message=message)]

def safe_json_parse(data: str) -> Optional[Dict[str, Any]]:
"""Safely parse JSON data."""
Expand Down