← Files CrowdStrike Falcon FoundryARCHIVED FILE
use-cases/greynoise-deep-dive.md
5.12 KB · Oct 4, 2026 · 12:31 UTC
---
name: greynoise-deep-dive
description: Build a multi-capability Foundry app that imports third-party threat intel into Falcon Next-Gen SIEM as a lookup file
source: https://www.crowdstrike.com/tech-hub/ng-siem/technical-deep-dive-with-greynoise-building-a-falcon-foundry-app-for-crowdstrike-falcon-next-gen-siem/
skills: [api-integrations, ui-development, functions-development, workflows-development]
capabilities: [api-integration, ui-page, function, workflow]
---
## When to Use
User wants to build a Foundry app that pulls data from an external API, transforms it into
a CSV lookup file, and uploads it to Falcon Next-Gen SIEM. Applies to any third-party threat
intel feed (GreyNoise, VirusTotal, AlienVault OTX, etc.) or bulk data import pattern.
## Pattern
1. **Define API integration** for the external service (GreyNoise, etc.) with necessary endpoints.
2. **Create a Python function** that:
- Calls the external API to fetch indicator data
- Processes results in batches (10K records per batch) to stay within memory limits
- Writes only needed fields to a CSV temp file
- Uploads the CSV via the FalconPy `NGSIEM.upload_file()` lookup API
3. **Increase function resource limits** in manifest for large data processing.
4. **Create a workflow** with a schedule trigger that invokes the function periodically.
5. **Add `humio-auth-proxy:write` scope** for lookup file upload permissions.
6. **Test locally** using Docker via `foundry functions run`, send curl requests to the container.
## Key Code
### Function imports and handler
```python
from crowdstrike.foundry.function import APIError, Function, Request, Response
from falconpy import NGSIEM
from greynoise.api import GreyNoise, APIConfig # or any third-party SDK
import pandas as pd
import tempfile, os, csv, gc
func = Function.instance()
@func.handler(method="POST", path="/greynoise-ti-import-bulk")
def on_post(request: Request, config, logger) -> Response:
logger.info("Starting NGSIEM CSV import process")
# ... fetch, process, upload
```
### Batch processing to stay within memory limits
```python
batch_data = response["data"]
rows_to_write = []
for i, item in enumerate(batch_data):
if processed_count >= max_indicator_count:
break
row = process_record(item, total_records + i + 1, logger)
if row is not None:
rows_to_write.append(row)
processed_count += 1
if rows_to_write:
writer.writerows(rows_to_write)
# Free memory after each batch
del batch_data, rows_to_write
gc.collect()
```
### File size guard (lookup upload limit is 50 MB)
```python
file_size = os.path.getsize(output_path)
logger.info(f"CSV file size: {file_size} bytes ({file_size / 1024 / 1024:.2f} MB)")
if file_size > 47_000_000: # buffer below 50 MB limit
logger.warning("File size > 47MB, stopping processing")
break
```
### Upload lookup file via FalconPy
```python
ngsiem = NGSIEM()
response = ngsiem.upload_file(lookup_file=output_path, repository=repository)
logger.info(f"API response: {response}")
```
### Manifest: extended function resources and required scope
```yaml
functions:
- name: greynoise-ti-import-to-ng-siem
language: python
max_exec_duration_seconds: 900 # max allowed runtime
max_exec_memory_mb: 1024 # max allowed memory
handlers:
- name: greynoise-ti-import-bulk
method: POST
api_path: /greynoise-ti-import-bulk
workflow_integration:
disruptive: false
system_action: false
auth:
scopes:
- humio-auth-proxy:write # REQUIRED for lookup file upload
```
### Local testing via Docker
```bash
foundry functions run # starts Docker container on random port
curl --request POST --url http://localhost:<port>/ \
--header 'content-type: application/json' \
--data '{
"body": {
"api_key": "KEY",
"max_indicator_count": "1000000",
"query": "last_seen:1d -classification:unknown",
"repository": "search-all"
},
"method": "POST",
"url": "/greynoise-ti-import-bulk"
}'
```
## Gotchas
- **Lookup file upload limit is 50 MB**, not what the console displays. Add a file size guard at ~47 MB to leave buffer. This limit may increase in the future.
- **Memory is capped at 1024 MB**. Process API responses in batches (e.g., 10K records), write to CSV immediately, then delete the batch and run `gc.collect()`.
- **Max execution time is 900 seconds**. Budget time across API fetch, CSV write, and upload. Log progress to track where time is spent.
- **`humio-auth-proxy:write` scope is required** for `NGSIEM.upload_file()`. Missing this scope causes silent upload failures (function reports success, but no lookup file appears).
- **403 during local Docker testing is expected**: the container can't authenticate to upload. Verify CSV generation locally, test upload after deploy.
- **Workflow inputs must match function request schema**: Define function parameters (`api_key`, `query`, `repository`, `max_indicator_count`) in the manifest request schema and wire them as workflow inputs.
- **Reference app**: [CrowdStrike/foundry-sample-ngsiem-importer](https://github.com/CrowdStrike/foundry-sample-ngsiem-importer) provides the base lookup file upload pattern.
SHA-256: 6f950020c91283e6ecf1093d4b8e27ebb63a1b8bc4512a188ff71c11def70723