Package: crowdstrike-foundry-function
Foundry Function as a Service Python SDKfoundry-fn-pythonis a community-driven, open source project designed to enable the authoring of functions.
While not a formal CrowdStrike product,foundry-fn-pythonis maintained by CrowdStrike and supported in partnership
with the open source developer community.Installation ⚙️ViapipThe SDK can be installed or updated viapip install:python3-mpipinstallcrowdstrike-foundry-functionQuickstart 💫CodeAdd the SDK to your project by following theinstallationinstructions above,
then create yourhandler.py:fromcrowdstrike.foundry.functionimport(APIError,Request,Response,Function,)func=Function.instance()# *** (1) ***@func.handler(method='POST',path='/create')# *** (2) ***defon_create(request:Request,config:[dict[str,any],None])->Response:# *** (3), (4) ***iflen(request.body)==0:returnResponse(code=400,errors=[APIError(code=400,message='empty body')])###### do something useful#####returnResponse(# *** (5) ***body={'hello':'world'},code=200,)if__name__=='__main__':func.run()# *** (6) ***Function: TheFunctionclass wraps the Foundry Function implementation.
EachFunctioninstance consists of a number of handlers, with each handler corresponding to an endpoint.
Only oneFunctionshould exist per Python implementation.
MultipleFunctions will result in undefined behavior.@func.handler: The handler decorator defines a Python function/method as an endpoint.
At a minimum, thehandlermust have amethodand apath.
Themethodmust be one ofDELETE,GET,PATCH,POST, andPUT.
Thepathcorresponds to theurlfield in the request.
The SDK will provide any loaded configuration as an argument.Methods decorated with@handlermust take arguments in the order ofRequestanddict|None(i.e. the request and either the configuration or nothing; see example above),
and must return aResponse.request: Request payload and metadata. At the time of this writing, theRequestobject consists of:body: The request payload as given in the Function Gatewaybodypayload field. Will be deserialized as
adict[str, Any].params: Contains request headers and query parameters.url: The request path relative to the function as a string.method: The request HTTP method or verb.access_token: Caller-supplied access token.Return from a@handlerfunction: Returns aResponseobject.
TheResponseobject contains fieldsbody(payload of the response as adict),code(anintrepresenting an HTTP status code),errors(a list of anyAPIErrors), andheader(adict[str, list[str]]of any special HTTP headers which
should be present on the response).
If nocodeis provided but a list oferrorsis, thecodewill be derived from the greatest positive valid HTTP
code present on the givenAPIErrors.func.run(): Runner method and general starting point of execution.
Callingrun()causes theFunctionto finish initializing and start executing.
Any code declared following this method may not necessarily be executed.
As such, it is recommended to place this as the last line of your script.Testing locallyThe SDK provides an out-of-the-box runtime for executing the function.
A basic HTTP server will be listening on port 8081.cdmy-project&&python3main.pyRequests can now be made against the executable.curl-XPOST'http://localhost:8081'\-H'Content-Type: application/json'\--data'{"body": {"foo": "bar"},"method": "POST","url": "/create"}'Convenience Functionality 🧰falconpyFoundry Function Python ships withfalconpypre-integrated and a convenience
constructor.
While it is not strictly necessary to use the convenience function, it is recommended.Important:Create a new instance of eachfalconpyclient you want on each request.# omitting other importsfromfalconpy.alertsimportAlertsfromfalconpy.event_streamsimportEventStreamsfromcrowdstrike.foundry.functionimportfalcon_client,Functionfunc=Function.instance()@func.handler(...)defendpoint(request,config):# ... omitting other code ...# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!# !!! create a new client instance on each request !!!# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!alerts_client=falcon_client(Alerts)event_streams_client=falcon_client(EventStreams)# ... omitting other code ...WE STOP BREACHES