@crowdstrike/foundry-js
v0.21.0
Published
foundry-js is the JavaScript SDK for authoring UI Extensions for CrowdStrike's Foundry platform.
Readme

@crowdstrike/foundry-js
The foundry-js JavaScript library provides convenient access to CrowdStrike's Foundry API for authoring UI pages and extensions.
Installation
npm install @crowdstrike/foundry-js
# or
yarn add @crowdstrike/foundry-js
# or
pnpm add @crowdstrike/foundry-jsOverview 🔎
SDK provides abstractions to build Foundry Pages, Extensions and interact with Foundry artifacts - Workflows, Collections, LogScale, API Integrations and CrowdStrike APIs.
Usage
When application starts, it should establish connection to Falcon Console. If connection is not establishes in first 5 seconds - app or extension will be dropped from loading on the page.
import FalconApi from '@crowdstrike/foundry-js';
(async () => {
const falcon = new FalconApi();
await falcon.connect();
});Receive events from Falcon Console
When UI extensions is loaded, it might receive data for the context it is loaded,
for example if UI extension was built for Detection side panel, it will receive detection associated data.
If data is updated in Falcon Console - event will automatically execute and pass new data.
(async () => {
falcon.events.on('data', (data) => {
// store received `data` and use it inside your application
});
});Working with Workflows
To call on-demand workflow:
(async () => {
const config = { name: 'WorkflowName', depth: 0 };
const pendingResult = await falcon.api.workflows.postEntitiesExecuteV1({}, config);
const result = await falcon.api.workflows.getEntitiesExecutionResultsV1({ ids: triggerResult.resources[0] });
});Working with Collections
(async () => {
const sampleData = {
"name": "John",
"age": 42,
"aliases": ["Doe", "Foundry"]
};
const collection = falcon
.collection({collection: '<collectionName>' });
// to write a collection
const result = await collection.write('test-key', sampleData);
// read collection
const record = await collection.read('test-key');
// record.age === 42
// search collection, `filter` does NOT use FQL (Falcon Query Language). An exact match for the name has to be used in this example below
const searchResult = await collection.search({ filter: `name:'exact-name-value'` });
// list the object keys in the collection, pagination is supported using; `start`, `end` and `limit`.
const listResult = await collection.list({ start, end, limit });
// deletes record
const deleteResponse = await collection.delete('test-key');
});Working with LogScale
(async () => {
// write to LogScale
const writeResult = await falcon.logscale.write({ test: 'check' });
// writeResult.resources?.[0]?.rows_written === 1
// run dynamic query
const queryResult = await falcon.logscale.query({ search_query: "*", start: "1h" });
// queryResult.resources?.[0]?.event_count > 0
// run saved query
const savedQueryResult = await falcon.logscale.savedQuery({ id: "<savedQueryId>", start: "30d", mode: 'sync' });
// savedQueryResult.resources?.[0]?.event_count > 0
});Working with API Integration
To call API Integration, App should be initially provisioned, and configuration for API Integration should be set up.
(async () => {
// we assume, that API Integration was created and operation Get Cities exists
const apiIntegration = falcon.apiIntegration({
definitionId: '<api-integration-id from manifest.yml>',
operationId: 'Get Cities',
});
const response = await apiIntegration.execute({
request: {
params: {
path: {
country: 'Spain'
}
}
}
});
// response.resources?.[0]?.status_code === 200
// date is at response.resources[0].response_body
});Working with Cloud Functions
(async () => {
const config = {
name: 'CloudFunctionName',
version: 1
};
const cloudFunction = falcon.cloudFunction(config);
// you can specify path parameters that will be passsed to your Cloud Function.
// `id` and `mode` - example query params that your Cloud Function will receive
const getResponse = await cloudFunction.path('/?id=150&mode=compact')
.get();
// you can call different HTTP methods - GET, POST, PATCH, PUT, DELETE
const postResponse = await cloudFunction.path('/')
.post({ name: 'test' });
const patchResponse = cloudFunction.path('/')
.patch({ name: 'test' });
const putResponse = cloudFunction.path('/')
.put({ name: 'test' });
const deleteResponse = cloudFunction.path('/?id=100')
.delete();
});Navigation utilities
As the Page or UI extension will run inside a sandboxed iframe, the navigateTo method must be used to change the url of the parent context (Falcon Console).
To open an external url (in a new tab):
falcon.navigation.navigateTo({
path: 'https://www.github.com',
});To navigate to a new url within Falcon Console:
falcon.navigation.navigateTo({
path: '/login',
type: "falcon",
});Modal utility
To open a modal within Falcon Console, rendering UI extension of your choice:
const result = await api.ui.openModal(
{
id: '<extension ID as defined in the manifest>',
type: 'extension' // 'extension' | 'page'
},
'Modal title',
{
path: '/', // initial path that will be set when page or extension loads
data: { foo: 'bar' }, // data to pass to the modal
size: 'lg', // width of the modal - 'sm', 'md', 'lg', 'xl'. 'md' is default
align: 'top', // vertical alignment - 'top' or undefined
} // OpenModalOptions
);
// to close modal:
await api.ui.closeModal();
await api.ui.closeModal({ foo: 'bar' });// you can pass payloadSample apps
| Application | Framework | |------------------------------------------------------------------------------------|-----------| | Triage with MITRE Attack | Vue | | Scalable RTR | React | | Rapid Response | React |
Additionally
| | Description | |-------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| | Javascript Blueprint | Starter Javascript blueprint used in Foundry CLI | | React Blueprint | Starter React blueprint used in Foundry CLI | | Falcon Shoelace | Shoelace Library of web components styled to fit in Falcon Console |
