feat(crowdstrike): expand to full command set (81 commands)

Adds device/IOC/process enrichment, host groups, cases, RTR
scripts/files/responders, ML/IOA exclusions, quarantine, Spotlight/CVE,
ODS scans, CSPM, users, IOA rules, CNAPP, detection resolve, workflows,
and identity (GraphQL). OAuth2 client-credentials, code-first scripts.

Excludes XSOAR-only plumbing (fetch/mirroring), deprecated legacy
commands, and binary/long-poll flows (retrieve-file, ngsiem search).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guillaume BOURGEOIS
2026-06-25 23:49:40 +02:00
parent d85a955e77
commit 17faa01103
66 changed files with 4572 additions and 0 deletions
+807
View File
@@ -226,3 +226,810 @@ commands:
timeout: { type: number, description: "Command timeout in seconds (default 30)." } timeout: { type: number, description: "Command timeout in seconds (default 30)." }
required: [host_id, process_ids] required: [host_id, process_ids]
outputs_schema: { properties: {} } outputs_schema: { properties: {} }
- id: search_custom_iocs
name: crowdstrike-search-custom-iocs
description: "Search custom IOC indicators using optional FQL filter parts (type, value, source, expiration)."
risk: read
inputs_schema:
properties:
types: { type: string, description: "Indicator type filter value, e.g. domain or sha256." }
values: { type: string, description: "Indicator value filter." }
sources: { type: string, description: "Source label filter." }
expiration: { type: string, description: "Expiration date filter (ISO 8601)." }
limit: { type: string, description: "Max results to return (default 50)." }
sort: { type: string, description: "Sort expression, e.g. created_on.desc." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: get_custom_ioc
name: crowdstrike-get-custom-ioc
description: "Retrieve a custom IOC indicator by its ID."
risk: read
inputs_schema:
properties:
ioc_id: { type: string, description: "IOC indicator ID to retrieve." }
required: [ioc_id]
outputs_schema: { properties: {} }
- id: update_custom_ioc
name: crowdstrike-update-custom-ioc
description: "Update an existing custom IOC indicator (action, platforms, severity, source, description, expiration)."
risk: destructive
inputs_schema:
properties:
ioc_id: { type: string, description: "IOC indicator ID to update." }
action: { type: string, description: "Action: no_action, allow, prevent_no_ui, prevent, or detect." }
platforms: { type: string, description: "Comma-separated platforms: windows, mac, linux." }
severity: { type: string, description: "Severity: informational, low, medium, high, or critical." }
source: { type: string, description: "Source label." }
description: { type: string, description: "Description text." }
expiration: { type: string, description: "Expiration date (ISO 8601)." }
required: [ioc_id]
outputs_schema: { properties: {} }
- id: batch_upload_custom_ioc
name: crowdstrike-batch-upload-custom-ioc
description: "Create multiple custom IOC indicators in a single call by providing a JSON array of indicator objects."
risk: destructive
inputs_schema:
properties:
multiple_indicators_json: { type: string, description: "JSON array string of indicator objects to create." }
required: [multiple_indicators_json]
outputs_schema: { properties: {} }
- id: processes_ran_on
name: crowdstrike-processes-ran-on
description: "List process IDs that ran a given indicator on a specific device."
risk: read
inputs_schema:
properties:
type: { type: string, description: "Indicator type: sha256, sha1, md5, domain, ipv4, or ipv6." }
value: { type: string, description: "Indicator value." }
device_id: { type: string, description: "Device ID to scope the query." }
required: [type, value, device_id]
outputs_schema: { properties: {} }
- id: process_details
name: crowdstrike-process-details
description: "Retrieve full details for one or more processes by process ID."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated process IDs." }
required: [ids]
outputs_schema: { properties: {} }
- id: device_ran_on
name: crowdstrike-device-ran-on
description: "List device IDs on which a given indicator has been observed."
risk: read
inputs_schema:
properties:
type: { type: string, description: "Indicator type: sha256, sha1, md5, domain, ipv4, or ipv6." }
value: { type: string, description: "Indicator value." }
required: [type, value]
outputs_schema: { properties: {} }
- id: create_host_group
name: crowdstrike-create-host-group
description: "Create a new host group (static or dynamic) with an optional description and assignment rule."
risk: safe_write
inputs_schema:
properties:
name: { type: string, description: "Name for the new host group." }
group_type: { type: string, description: "Group type: static or dynamic." }
description: { type: string, description: "Optional description for the host group." }
assignment_rule: { type: string, description: "Optional FQL assignment rule (required for dynamic groups)." }
required: [name, group_type]
outputs_schema: { properties: {} }
- id: update_host_group
name: crowdstrike-update-host-group
description: "Update an existing host group's name, description, or assignment rule."
risk: safe_write
inputs_schema:
properties:
host_group_id: { type: string, description: "ID of the host group to update." }
name: { type: string, description: "New name for the host group." }
description: { type: string, description: "New description for the host group." }
assignment_rule: { type: string, description: "New FQL assignment rule for dynamic groups." }
required: [host_group_id]
outputs_schema: { properties: {} }
- id: delete_host_groups
name: crowdstrike-delete-host-groups
description: "Delete one or more host groups by ID."
risk: destructive
inputs_schema:
properties:
host_group_id: { type: string, description: "Comma-separated host group IDs to delete." }
required: [host_group_id]
outputs_schema: { properties: {} }
- id: list_host_group_members
name: crowdstrike-list-host-group-members
description: "List devices that are members of a host group, with optional FQL filter and pagination."
risk: read
inputs_schema:
properties:
host_group_id: { type: string, description: "Host group ID to list members of." }
filter: { type: string, description: "Optional FQL filter to narrow results." }
limit: { type: string, description: "Max members to return (default 50)." }
offset: { type: string, description: "Pagination offset." }
sort: { type: string, description: "Sort expression, e.g. hostname.asc." }
required: []
outputs_schema: { properties: {} }
- id: add_host_group_members
name: crowdstrike-add-host-group-members
description: "Add one or more hosts to a host group by device ID."
risk: safe_write
inputs_schema:
properties:
host_group_id: { type: string, description: "ID of the host group to add hosts to." }
host_ids: { type: string, description: "Comma-separated device IDs to add." }
required: [host_group_id, host_ids]
outputs_schema: { properties: {} }
- id: remove_host_group_members
name: crowdstrike-remove-host-group-members
description: "Remove one or more hosts from a host group by device ID."
risk: safe_write
inputs_schema:
properties:
host_group_id: { type: string, description: "ID of the host group to remove hosts from." }
host_ids: { type: string, description: "Comma-separated device IDs to remove." }
required: [host_group_id, host_ids]
outputs_schema: { properties: {} }
# ── Cases ─────────────────────────────────────────────────────────────────
- id: list_case_summaries
name: crowdstrike-list-case-summaries
description: "List case summaries. If ids are provided, fetches those specific cases; otherwise queries all cases sorted by creation date and returns their summaries."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated case IDs (optional). If omitted, all cases are listed." }
required: []
outputs_schema: { properties: {} }
- id: get_evidence_for_case
name: crowdstrike-get-evidence-for-case
description: "Retrieve full case details including evidence for a single case by ID. Evidence is available at resources[0].evidence in the response."
risk: read
inputs_schema:
properties:
id: { type: string, description: "Case ID." }
required: [id]
outputs_schema: { properties: {} }
- id: add_case_tag
name: crowdstrike-add-case-tag
description: "Add one or more tags to an existing case."
risk: safe_write
inputs_schema:
properties:
id: { type: string, description: "Case ID." }
tags: { type: string, description: "Comma-separated tags to add." }
required: [id, tags]
outputs_schema: { properties: {} }
- id: delete_case_tag
name: crowdstrike-delete-case-tag
description: "Remove a single tag from an existing case."
risk: safe_write
inputs_schema:
properties:
id: { type: string, description: "Case ID." }
tag: { type: string, description: "Tag to remove." }
required: [id, tag]
outputs_schema: { properties: {} }
- id: resolve_case
name: crowdstrike-resolve-case
description: "Update a case: change status, name, description, assigned analyst, or severity."
risk: destructive
inputs_schema:
properties:
id: { type: string, description: "Case ID." }
status: { type: string, description: "New case status (optional)." }
name: { type: string, description: "New case name (optional)." }
assigned_to_uuid: { type: string, description: "UUID of the analyst to assign the case to (optional)." }
description: { type: string, description: "Updated case description (optional)." }
severity: { type: number, description: "Severity level as an integer (optional)." }
required: [id]
outputs_schema: { properties: {} }
- id: list_detection_summaries
name: crowdstrike-list-detection-summaries
description: "List alert/detection summaries. Accepts explicit composite IDs or an FQL filter to query alerts first, then fetches full entities."
risk: read
inputs_schema:
properties:
fetch_query: { type: string, description: "FQL filter to query alerts (optional, used when ids are not provided)." }
ids: { type: string, description: "Comma-separated alert composite IDs (optional). Takes priority over fetch_query." }
required: []
outputs_schema: { properties: {} }
- id: endpoint
name: crowdstrike-endpoint
description: "Look up a device/endpoint by device ID, local IP, or hostname; returns full device details for matches."
risk: read
inputs_schema:
properties:
id: { type: string, description: "Device ID to match (optional)." }
ip: { type: string, description: "Local IP address to match (optional)." }
hostname: { type: string, description: "Hostname to match (optional)." }
required: []
outputs_schema: { properties: {} }
# RTR script/file management and extended Real Time Response commands
# Fragment — matches manifest.yaml command block format
- id: upload_script
name: crowdstrike-upload-script
description: "Upload a PowerShell script to the RTR cloud script library."
risk: safe_write
inputs_schema:
properties:
name: { type: string, description: "Script name (unique identifier in the library)." }
permission_type: { type: string, description: "Visibility: private, group, or public (default private)." }
content: { type: string, description: "PowerShell script content." }
required: [name, content]
outputs_schema: { properties: {} }
- id: get_script
name: crowdstrike-get-script
description: "Retrieve one or more RTR cloud scripts by ID."
risk: read
inputs_schema:
properties:
script_id: { type: string, description: "Comma-separated script IDs." }
required: [script_id]
outputs_schema: { properties: {} }
- id: delete_script
name: crowdstrike-delete-script
description: "Delete an RTR cloud script by ID."
risk: destructive
inputs_schema:
properties:
script_id: { type: string, description: "Script ID to delete." }
required: [script_id]
outputs_schema: { properties: {} }
- id: list_scripts
name: crowdstrike-list-scripts
description: "List all RTR cloud scripts available in the tenant."
risk: read
inputs_schema:
properties: {}
required: []
outputs_schema: { properties: {} }
- id: list_files
name: crowdstrike-list-files
description: "List all RTR PUT files (files available for deployment to hosts)."
risk: read
inputs_schema:
properties: {}
required: []
outputs_schema: { properties: {} }
- id: get_file
name: crowdstrike-get-file
description: "Retrieve one or more RTR PUT files by ID."
risk: read
inputs_schema:
properties:
file_id: { type: string, description: "Comma-separated PUT file IDs." }
required: [file_id]
outputs_schema: { properties: {} }
- id: delete_file
name: crowdstrike-delete-file
description: "Delete an RTR PUT file by ID."
risk: destructive
inputs_schema:
properties:
file_id: { type: string, description: "PUT file ID to delete." }
required: [file_id]
outputs_schema: { properties: {} }
- id: refresh_session
name: crowdstrike-refresh-session
description: "Refresh an existing RTR session for a host, extending its TTL."
risk: safe_write
inputs_schema:
properties:
host_id: { type: string, description: "Device ID of the host whose session to refresh." }
required: [host_id]
outputs_schema: { properties: {} }
- id: list_host_files
name: crowdstrike-list-host-files
description: "List files extracted from an RTR session on a specific host. Opens a new session if no session_id is provided."
risk: read
inputs_schema:
properties:
host_id: { type: string, description: "Device ID of the target host." }
session_id: { type: string, description: "Existing RTR session ID (optional; a new session is opened if omitted)." }
required: [host_id]
outputs_schema: { properties: {} }
- id: rtr_remove_file
name: crowdstrike-rtr-remove-file
description: "Open an RTR batch session and remove a file from one or more hosts using the rm command."
risk: destructive
inputs_schema:
properties:
host_ids: { type: string, description: "Comma-separated device IDs." }
file_path: { type: string, description: "Full path of the file to remove on the host." }
os: { type: string, description: "Target OS: Windows, Linux, or Mac." }
queue_offline: { type: string, description: "Queue command for offline hosts: true or false (default false)." }
timeout: { type: string, description: "Command timeout in seconds (default 30)." }
required: [host_ids, file_path, os]
outputs_schema: { properties: {} }
- id: rtr_list_network_stats
name: crowdstrike-rtr-list-network-stats
description: "Open an RTR batch session on a single host and run netstat to list active network connections."
risk: read
inputs_schema:
properties:
host_id: { type: string, description: "Device ID of the target host." }
queue_offline: { type: string, description: "Queue command for offline hosts: true or false (default false)." }
timeout: { type: string, description: "Command timeout in seconds (default 30)." }
required: [host_id]
outputs_schema: { properties: {} }
- id: rtr_list_scheduled_tasks
name: crowdstrike-rtr-list-scheduled-tasks
description: "Open an RTR batch session and enumerate scheduled tasks on Windows hosts via schtasks."
risk: read
inputs_schema:
properties:
host_ids: { type: string, description: "Comma-separated device IDs." }
queue_offline: { type: string, description: "Queue command for offline hosts: true or false (default false)." }
timeout: { type: string, description: "Command timeout in seconds (default 30)." }
required: [host_ids]
outputs_schema: { properties: {} }
# ── ML Exclusions ──────────────────────────────────────────────────────────
- id: create_ml_exclusion
name: crowdstrike-create-ml-exclusion
description: "Create a new ML exclusion to prevent the machine learning engine from triggering on a specific value."
risk: destructive
inputs_schema:
properties:
value: { type: string, description: "The exclusion value (e.g. file path or hash)." }
excluded_from: { type: string, description: "Comma-separated list of ML detection categories to exclude from (e.g. blocking,extraction)." }
comment: { type: string, description: "Optional comment describing the reason for the exclusion." }
groups: { type: string, description: "Comma-separated host group IDs to scope the exclusion. Defaults to all groups." }
required: [value, excluded_from]
outputs_schema: { properties: {} }
- id: update_ml_exclusion
name: crowdstrike-update-ml-exclusion
description: "Update an existing ML exclusion by ID (value, comment, or groups)."
risk: destructive
inputs_schema:
properties:
id: { type: string, description: "ML exclusion ID to update." }
value: { type: string, description: "New exclusion value (optional)." }
comment: { type: string, description: "Updated comment (optional)." }
groups: { type: string, description: "Comma-separated host group IDs to replace the current scoping (optional)." }
required: [id]
outputs_schema: { properties: {} }
- id: delete_ml_exclusion
name: crowdstrike-delete-ml-exclusion
description: "Delete one or more ML exclusions by ID."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated ML exclusion IDs to delete." }
required: [ids]
outputs_schema: { properties: {} }
- id: search_ml_exclusion
name: crowdstrike-search-ml-exclusion
description: "Search ML exclusions by explicit IDs, a value substring match, or an FQL filter; returns full exclusion entities."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated exclusion IDs (takes priority over value and filter)." }
value: { type: string, description: "Value substring to search for (takes priority over filter when ids is absent)." }
filter: { type: string, description: "FQL filter string (used when neither ids nor value is provided)." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
sort: { type: string, description: "Sort expression, e.g. value.asc." }
required: []
outputs_schema: { properties: {} }
# ── IOA Exclusions ─────────────────────────────────────────────────────────
- id: create_ioa_exclusion
name: crowdstrike-create-ioa-exclusion
description: "Create a new IOA exclusion to suppress a specific Indicator of Attack pattern."
risk: destructive
inputs_schema:
properties:
exclusion_name: { type: string, description: "Display name for the IOA exclusion." }
pattern_id: { type: string, description: "ID of the IOA pattern to exclude." }
cl_regex: { type: string, description: "Command-line regular expression to match." }
ifn_regex: { type: string, description: "Image filename regular expression to match." }
pattern_name: { type: string, description: "Human-readable pattern name (optional)." }
comment: { type: string, description: "Optional comment." }
description: { type: string, description: "Optional description." }
groups: { type: string, description: "Comma-separated host group IDs to scope the exclusion. Defaults to all groups." }
detection_json: { type: string, description: "Optional detection JSON override." }
required: [exclusion_name, pattern_id, cl_regex, ifn_regex]
outputs_schema: { properties: {} }
- id: update_ioa_exclusion
name: crowdstrike-update-ioa-exclusion
description: "Update an existing IOA exclusion by ID."
risk: destructive
inputs_schema:
properties:
id: { type: string, description: "IOA exclusion ID to update." }
exclusion_name: { type: string, description: "New display name (optional)." }
pattern_id: { type: string, description: "New pattern ID (optional)." }
pattern_name: { type: string, description: "New pattern name (optional)." }
cl_regex: { type: string, description: "New command-line regex (optional)." }
ifn_regex: { type: string, description: "New image filename regex (optional)." }
comment: { type: string, description: "Updated comment (optional)." }
description: { type: string, description: "Updated description (optional)." }
groups: { type: string, description: "Comma-separated host group IDs to replace current scoping (optional)." }
detection_json: { type: string, description: "Updated detection JSON (optional)." }
required: [id]
outputs_schema: { properties: {} }
- id: delete_ioa_exclusion
name: crowdstrike-delete-ioa-exclusion
description: "Delete one or more IOA exclusions by ID."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated IOA exclusion IDs to delete." }
required: [ids]
outputs_schema: { properties: {} }
- id: search_ioa_exclusion
name: crowdstrike-search-ioa-exclusion
description: "Search IOA exclusions by explicit IDs, a name substring match, or an FQL filter; returns full exclusion entities."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated exclusion IDs (takes priority over name and filter)." }
name: { type: string, description: "Name substring to search for (takes priority over filter when ids is absent)." }
filter: { type: string, description: "FQL filter string (used when neither ids nor name is provided)." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
# ── Quarantine ─────────────────────────────────────────────────────────────
- id: list_quarantined_file
name: crowdstrike-list-quarantined-file
description: "List quarantined files by explicit IDs or an FQL filter query."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated quarantined file IDs (takes priority over filter)." }
filter: { type: string, description: "FQL filter string (used when ids is absent)." }
limit: { type: string, description: "Max results to return (default 50)." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: apply_quarantine_file_action
name: crowdstrike-apply-quarantine-file-action
description: "Apply an action (delete, release, or unrelease) to one or more quarantined files."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated quarantined file IDs." }
action: { type: string, description: "Action to apply: delete, release, or unrelease." }
comment: { type: string, description: "Comment explaining the reason for the action." }
required: [ids, action, comment]
outputs_schema: { properties: {} }
# ── Spotlight CVE ──────────────────────────────────────────────────────────
- id: cve
name: crowdstrike-cve
description: "Retrieve Falcon Spotlight vulnerability details for one or more CVE IDs, including CVE facet metadata."
risk: read
inputs_schema:
properties:
cve: { type: string, description: "Comma-separated CVE IDs to look up (e.g. CVE-2021-44228,CVE-2022-3786)." }
required: [cve]
outputs_schema: { properties: {} }
- id: spotlight_list_host_by_vulnerability
name: crowdstrike-spotlight-list-host-by-vulnerability
description: "List hosts affected by one or more CVE IDs using Falcon Spotlight, with host_info facet details."
risk: read
inputs_schema:
properties:
cve_ids: { type: string, description: "Comma-separated CVE IDs to filter by (e.g. CVE-2021-44228)." }
limit: { type: string, description: "Max results to return (default 50)." }
required: [cve_ids]
outputs_schema: { properties: {} }
# ── ODS — On-Demand Scans ────────────────────────────────────────────────────
- id: ods_query_scan
name: crowdstrike-ods-query-scan
description: "Query ODS scans by ID or FQL filter. If ids provided, fetch those scans directly; otherwise query and resolve."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated scan IDs to retrieve directly." }
filter: { type: string, description: "FQL filter to narrow query results." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: ods_query_scheduled_scan
name: crowdstrike-ods-query-scheduled-scan
description: "Query ODS scheduled scans by ID or FQL filter. If ids provided, fetch those scans directly; otherwise query and resolve."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated scheduled scan IDs to retrieve directly." }
filter: { type: string, description: "FQL filter to narrow query results." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: ods_query_scan_host
name: crowdstrike-ods-query-scan-host
description: "Query ODS scan hosts by ID or FQL filter. If ids provided, fetch those scan-host records directly; otherwise query and resolve."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated scan-host IDs to retrieve directly." }
filter: { type: string, description: "FQL filter to narrow query results." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: ods_query_malicious_files
name: crowdstrike-ods-query-malicious-files
description: "Query ODS malicious files by file_ids or FQL filter. If file_ids provided, fetch those records directly; otherwise query and resolve."
risk: read
inputs_schema:
properties:
file_ids: { type: string, description: "Comma-separated malicious file IDs to retrieve directly." }
filter: { type: string, description: "FQL filter to narrow query results." }
limit: { type: string, description: "Max results to return." }
offset: { type: string, description: "Pagination offset." }
required: []
outputs_schema: { properties: {} }
- id: ods_create_scan
name: crowdstrike-ods-create-scan
description: "Create an ODS on-demand scan targeting specific hosts and/or host groups."
risk: destructive
inputs_schema:
properties:
hosts: { type: string, description: "Comma-separated device IDs to scan." }
host_groups: { type: string, description: "Comma-separated host group IDs to scan." }
file_paths: { type: string, description: "Comma-separated file paths to include in the scan." }
scan_inclusions: { type: string, description: "Comma-separated scan inclusion patterns." }
description: { type: string, description: "Optional description for the scan." }
quarantine: { type: string, description: "Quarantine detected malicious files: true or false." }
required: []
outputs_schema: { properties: {} }
- id: ods_create_scheduled_scan
name: crowdstrike-ods-create-scheduled-scan
description: "Create a recurring ODS scheduled scan for one or more host groups."
risk: destructive
inputs_schema:
properties:
host_groups: { type: string, description: "Comma-separated host group IDs (required)." }
file_paths: { type: string, description: "Comma-separated file paths to include." }
scan_inclusions: { type: string, description: "Comma-separated scan inclusion patterns." }
description: { type: string, description: "Optional description." }
schedule_start_timestamp: { type: string, description: "ISO 8601 start timestamp (required)." }
schedule_interval: { type: string, description: "Recurrence: Never, Daily, Weekly, Every other week, Every four weeks, or Monthly (required)." }
required: [host_groups, schedule_start_timestamp, schedule_interval]
outputs_schema: { properties: {} }
- id: ods_delete_scheduled_scan
name: crowdstrike-ods-delete-scheduled-scan
description: "Delete one or more ODS scheduled scans by ID."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated scheduled scan IDs to delete." }
required: [ids]
outputs_schema: { properties: {} }
# ── CSPM — Cloud Security Posture Management ──────────────────────────────────
- id: cspm_list_policy_details
name: crowdstrike-cspm-list-policy-details
description: "Retrieve CSPM policy details for one or more policy IDs."
risk: read
inputs_schema:
properties:
policy_ids: { type: string, description: "Comma-separated CSPM policy IDs." }
required: [policy_ids]
outputs_schema: { properties: {} }
- id: cspm_list_service_policy_settings
name: crowdstrike-cspm-list-service-policy-settings
description: "List CSPM service policy settings for a given policy ID and cloud platform."
risk: read
inputs_schema:
properties:
policy_id: { type: string, description: "CSPM policy ID." }
cloud_platform: { type: string, description: "Cloud platform: aws (default), azure, or gcp." }
service: { type: string, description: "Optional cloud service name to filter." }
limit: { type: string, description: "Max results to return." }
required: [policy_id]
outputs_schema: { properties: {} }
- id: cspm_update_policy_settings
name: crowdstrike-cspm-update-policy-settings
description: "Update CSPM policy settings: enable/disable, change severity, scope to regions or account."
risk: destructive
inputs_schema:
properties:
policy_id: { type: string, description: "CSPM policy ID to update (required)." }
account_id: { type: string, description: "Optional cloud account ID to scope the update." }
enabled: { type: string, description: "Enable policy: true (default) or false." }
regions: { type: string, description: "Comma-separated regions to scope the policy." }
severity: { type: string, description: "Optional severity override." }
tag_excluded: { type: string, description: "Exclude tagged resources: true or false." }
required: [policy_id]
outputs_schema: { properties: {} }
# ── Users / Rules / Alerts ────────────────────────────────────────────────────
- id: list_users
name: crowdstrike-list-users
description: "List Falcon users. If id provided, fetch those users directly; otherwise query with optional filter."
risk: read
inputs_schema:
properties:
id: { type: string, description: "Comma-separated user UUIDs to retrieve directly." }
filter: { type: string, description: "FQL filter to narrow query results." }
offset: { type: string, description: "Pagination offset (default 0)." }
limit: { type: string, description: "Max results to return (default 50)." }
required: []
outputs_schema: { properties: {} }
- id: get_ioarules
name: crowdstrike-get-ioarules
description: "Retrieve IOA (Indicator of Attack) custom rules by rule ID."
risk: read
inputs_schema:
properties:
rule_ids: { type: string, description: "Comma-separated IOA rule IDs." }
required: [rule_ids]
outputs_schema: { properties: {} }
- id: list_cnapp_alerts
name: crowdstrike-list-cnapp-alerts
description: "List CNAPP container security alerts, optionally filtered by FQL expression."
risk: read
inputs_schema:
properties:
filter: { type: string, description: "Optional FQL filter to narrow results." }
required: []
outputs_schema: { properties: {} }
- id: resolve_identity_detection
name: crowdstrike-resolve-identity-detection
description: "Resolve or update Falcon Identity Detection alerts: change status, assign, comment, tag, or unassign."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated composite alert IDs (required)." }
update_status: { type: string, description: "New status, e.g. new, in_progress, closed, or reopened." }
assign_to_uuid: { type: string, description: "Analyst UUID to assign the detection to." }
append_comment: { type: string, description: "Comment text to append." }
add_tag: { type: string, description: "Tag to add to the detection." }
remove_tag: { type: string, description: "Tag to remove from the detection." }
unassign: { type: string, description: "Unassign the detection: true or false." }
show_in_ui: { type: string, description: "Show in UI: true or false." }
required: [ids]
outputs_schema: { properties: {} }
- id: resolve_mobile_detection
name: crowdstrike-resolve-mobile-detection
description: "Resolve or update Falcon Mobile Detection alerts: change status, assign, comment, tag, or unassign."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated composite alert IDs (required)." }
update_status: { type: string, description: "New status, e.g. new, in_progress, closed, or reopened." }
assign_to_uuid: { type: string, description: "Analyst UUID to assign the detection to." }
append_comment: { type: string, description: "Comment text to append." }
add_tag: { type: string, description: "Tag to add to the detection." }
remove_tag: { type: string, description: "Tag to remove from the detection." }
unassign: { type: string, description: "Unassign the detection: true or false." }
show_in_ui: { type: string, description: "Show in UI: true or false." }
required: [ids]
outputs_schema: { properties: {} }
- id: list_workflow_definitions
name: crowdstrike-list-workflow-definitions
description: "List Falcon Fusion workflow definitions using an optional FQL filter, pagination offset/limit, and sort expression."
risk: read
inputs_schema:
properties:
filter: { type: string, description: "FQL filter expression." }
limit: { type: string, description: "Maximum number of results (default 50)." }
offset: { type: string, description: "Pagination offset (default 0)." }
sort: { type: string, description: "Sort expression, e.g. name.asc." }
required: []
outputs_schema: { properties: {} }
- id: workflow_execute
name: crowdstrike-workflow-execute
description: "Trigger execution of one or more Falcon Fusion workflow definitions."
risk: destructive
inputs_schema:
properties:
definition_id: { type: string, description: "Comma-separated workflow definition IDs to execute." }
name: { type: string, description: "Optional workflow name filter." }
key: { type: string, description: "Optional idempotency key for the execution." }
source_event_url: { type: string, description: "Optional source event URL." }
execution_cid: { type: string, description: "Comma-separated CIDs to target for execution." }
body: { type: string, description: "JSON string body to pass as the execution payload (default {})." }
required: [definition_id]
outputs_schema: { properties: {} }
- id: list_workflow_executions
name: crowdstrike-list-workflow-executions
description: "List Falcon Fusion workflow execution records using an optional FQL filter, pagination offset/limit, and sort expression."
risk: read
inputs_schema:
properties:
filter: { type: string, description: "FQL filter expression." }
limit: { type: string, description: "Maximum number of results (default 50)." }
offset: { type: string, description: "Pagination offset (default 0)." }
sort: { type: string, description: "Sort expression, e.g. start_timestamp.desc." }
required: []
outputs_schema: { properties: {} }
- id: list_workflow_execution_results
name: crowdstrike-list-workflow-execution-results
description: "Retrieve detailed results for one or more workflow execution IDs."
risk: read
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated workflow execution IDs." }
required: [ids]
outputs_schema: { properties: {} }
- id: workflow_execution_action
name: crowdstrike-workflow-execution-action
description: "Perform an action (cancel or resume) on one or more workflow executions."
risk: destructive
inputs_schema:
properties:
ids: { type: string, description: "Comma-separated workflow execution IDs." }
action_name: { type: string, description: "Action to perform: cancel or resume.", enum: [cancel, resume] }
required: [ids, action_name]
outputs_schema: { properties: {} }
- id: list_identity_entities
name: crowdstrike-list-identity-entities
description: "Query Falcon Identity Protection entities (users or endpoints) via the GraphQL API, returning risk scores and factors."
risk: read
inputs_schema:
properties:
type: { type: string, description: "Entity type: USER or ENDPOINT.", enum: [USER, ENDPOINT] }
limit: { type: string, description: "Maximum number of nodes to return (default 50)." }
primary_display_name: { type: string, description: "Optional filter by primary display name (informational; include in query if supported)." }
email: { type: string, description: "Optional filter by email address (informational; include in query if supported)." }
required: [type]
outputs_schema: { properties: {} }
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
id_ = INPUTS.get("id", "")
tags = INPUTS.get("tags", "")
result = call("POST", "/cases/entities/case-tags/v1", tok, body={"id": id_, "tags": csv(tags)})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,58 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_group_id = INPUTS.get("host_group_id", "")
host_ids = INPUTS.get("host_ids", "")
result = call(
"POST",
"/devices/entities/host-group-actions/v1",
tok,
params=[("action_name", "add-hosts")],
body={
"action_parameters": [{"name": "filter", "value": "(device_id:" + str(csv(host_ids)) + ")"}],
"ids": [host_group_id],
},
)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,55 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
action = INPUTS.get("action", "")
comment = INPUTS.get("comment", "")
body = {
"ids": csv(ids),
"action": action,
"comment": comment,
}
result = call("PATCH", "/quarantine/entities/quarantined-files/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
parsed = json.loads(INPUTS.get("multiple_indicators_json", "[]"))
result = call("POST", "/iocs/entities/indicators/v1", tok, body={"indicators": parsed})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,56 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
name = INPUTS.get("name", "")
group_type = INPUTS.get("group_type", "")
description = INPUTS.get("description", "")
assignment_rule = INPUTS.get("assignment_rule", "")
res = {"name": name, "group_type": group_type}
if description:
res["description"] = description
if assignment_rule:
res["assignment_rule"] = assignment_rule
result = call("POST", "/devices/entities/host-groups/v1", tok, body={"resources": [res]})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,73 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
exclusion_name = INPUTS.get("exclusion_name", "")
pattern_id = INPUTS.get("pattern_id", "")
cl_regex = INPUTS.get("cl_regex", "")
ifn_regex = INPUTS.get("ifn_regex", "")
pattern_name = INPUTS.get("pattern_name", "")
comment = INPUTS.get("comment", "")
description = INPUTS.get("description", "")
groups = INPUTS.get("groups", "")
detection_json = INPUTS.get("detection_json", "")
body = {
"name": exclusion_name,
"pattern_id": pattern_id,
"cl_regex": cl_regex,
"ifn_regex": ifn_regex,
"groups": csv(groups or "all"),
}
if pattern_name:
body["pattern_name"] = pattern_name
if comment:
body["comment"] = comment
if description:
body["description"] = description
if detection_json:
body["detection_json"] = detection_json
result = call("POST", "/policy/entities/ioa-exclusions/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,58 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
value = INPUTS.get("value", "")
excluded_from = INPUTS.get("excluded_from", "")
comment = INPUTS.get("comment", "")
groups = INPUTS.get("groups", "")
body = {
"value": value,
"excluded_from": csv(excluded_from),
"groups": csv(groups or "all"),
}
if comment:
body["comment"] = comment
result = call("POST", "/policy/entities/ml-exclusions/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
policy_ids = INPUTS.get("policy_ids", "")
result = call("GET", "/settings/entities/policy-details/v1", tok, params=[("ids", x) for x in csv(policy_ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,58 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
policy_id = INPUTS.get("policy_id", "")
cloud_platform = INPUTS.get("cloud_platform", "aws")
service = INPUTS.get("service", "")
limit = INPUTS.get("limit", "")
params = [("policy-id", policy_id), ("cloud-platform", cloud_platform)]
if service:
params.append(("service", service))
if limit:
params.append(("limit", limit))
result = call("GET", "/settings/entities/policy/v1", tok, params=params)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
policy_id = INPUTS.get("policy_id", "")
account_id = INPUTS.get("account_id", "")
enabled = INPUTS.get("enabled", "true")
regions = INPUTS.get("regions", "")
severity = INPUTS.get("severity", "")
tag_excluded = INPUTS.get("tag_excluded", "")
res = {
"policy_id": int(policy_id),
"enabled": (str(enabled).lower() == "true"),
}
if account_id:
res["account_id"] = account_id
if severity:
res["severity"] = severity
if regions:
res["regions"] = csv(regions)
if tag_excluded:
res["tag_excluded"] = (str(tag_excluded).lower() == "true")
result = call("PATCH", "/settings/entities/policy/v1", tok, body={"resources": [res]})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
+49
View File
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
cve = INPUTS.get("cve", "")
filt = "cve.id:['" + "','".join(csv(cve)) + "']"
result = call("GET", "/spotlight/combined/vulnerabilities/v1", tok, params=[("filter", filt), ("facet", "cve")])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
id_ = INPUTS.get("id", "")
tag = INPUTS.get("tag", "")
result = call("DELETE", "/cases/entities/case-tags/v1", tok, params=[("id", id_), ("tag", tag)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
file_id = INPUTS.get("file_id", "")
result = call("DELETE", "/real-time-response/entities/put-files/v1", tok,
params=[("ids", file_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_group_id = INPUTS.get("host_group_id", "")
result = call("DELETE", "/devices/entities/host-groups/v1", tok, params=[("ids", x) for x in csv(host_group_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
result = call("DELETE", "/policy/entities/ioa-exclusions/v1", tok, params=[("ids", x) for x in csv(ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
result = call("DELETE", "/policy/entities/ml-exclusions/v1", tok, params=[("ids", x) for x in csv(ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
script_id = INPUTS.get("script_id", "")
result = call("DELETE", "/real-time-response/entities/scripts/v1", tok,
params=[("ids", script_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
type_ = INPUTS.get("type", "")
value = INPUTS.get("value", "")
result = call("GET", "/indicators/queries/devices/v1", tok, params=[("type", type_), ("value", value)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,60 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
parts = []
if INPUTS.get("id"):
parts.append("device_id:'" + INPUTS.get("id") + "'")
if INPUTS.get("ip"):
parts.append("local_ip:'" + INPUTS.get("ip") + "'")
if INPUTS.get("hostname"):
parts.append("hostname:'" + INPUTS.get("hostname") + "'")
filt = "+".join(parts)
query = call("GET", "/devices/queries/devices/v1", tok, params=[("filter", filt), ("limit", "50")])
ids = query.get("resources", [])
if ids:
result = call("POST", "/devices/entities/devices/v2", tok, body={"ids": ids})
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ioc_id = INPUTS.get("ioc_id", "")
result = call("GET", "/iocs/entities/indicators/v1", tok, params=[("ids", ioc_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
id_ = INPUTS.get("id", "")
result = call("POST", "/cases/entities/cases/v2", tok, body={"ids": [id_]})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
file_id = INPUTS.get("file_id", "")
result = call("GET", "/real-time-response/entities/put-files/v2", tok,
params=[("ids", x) for x in csv(file_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
rule_ids = INPUTS.get("rule_ids", "")
result = call("GET", "/ioarules/entities/rules/v1", tok, params=[("ids", x) for x in csv(rule_ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
script_id = INPUTS.get("script_id", "")
result = call("GET", "/real-time-response/entities/scripts/v2", tok,
params=[("ids", x) for x in csv(script_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,53 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids_input = INPUTS.get("ids", "")
if ids_input:
result = call("POST", "/cases/entities/cases/v2", tok, body={"ids": csv(ids_input)})
else:
query = call("GET", "/cases/queries/cases/v1", tok, params=[("sort", "created_timestamp.asc"), ("limit", "100")])
resources = query.get("resources", [])
result = call("POST", "/cases/entities/cases/v2", tok, body={"ids": resources})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,53 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
filter_ = INPUTS.get("filter", "")
params = [("offset", "0"), ("limit", "100")]
if filter_:
params.append(("filter", filter_))
result = call("GET", "/container-security/combined/container-alerts/v1", tok, params=params)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,55 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids_input = INPUTS.get("ids", "")
if ids_input:
comp = csv(ids_input)
else:
fetch_query = INPUTS.get("fetch_query", "")
params = [("filter", fetch_query)] if fetch_query else []
query = call("GET", "/alerts/queries/alerts/v2", tok, params=params)
comp = query.get("resources", [])
result = call("POST", "/alerts/entities/alerts/v2", tok, body={"composite_ids": comp})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,47 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
result = call("GET", "/real-time-response/entities/put-files/v2", tok)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,54 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_id = INPUTS.get("host_id", "")
session_id = INPUTS.get("session_id", "")
if not session_id:
init = call("POST", "/real-time-response/entities/sessions/v1", tok,
body={"device_id": host_id})
session_id = init.get("resources", [{}])[0].get("session_id", "")
result = call("GET", "/real-time-response/entities/file/v2", tok,
params=[("session_id", session_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,63 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_group_id = INPUTS.get("host_group_id", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "50")
offset = INPUTS.get("offset", "")
sort = INPUTS.get("sort", "")
params = []
if host_group_id:
params.append(("id", host_group_id))
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
if sort:
params.append(("sort", sort))
result = call("GET", "/devices/combined/host-group-members/v1", tok, params=params if params else None)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
q = '{ entities(types: [%s], first: %s) { nodes { primaryDisplayName secondaryDisplayName riskScore riskScoreSeverity riskFactors { type severity } ... on UserEntity { emailAddresses } } } }' % (INPUTS.get("type", "USER"), str(INPUTS.get("limit", "50")))
result = call("POST", "/identity-protection/combined/graphql/v1", tok, body={"query": q})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "50")
offset = INPUTS.get("offset", "")
if ids:
q_ids = csv(ids)
else:
params = []
if filter_:
params.append(("filter", filter_))
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
resp = call("GET", "/quarantine/queries/quarantined-files/v1", tok, params=params)
q_ids = resp.get("resources", [])
if q_ids:
result = call("POST", "/quarantine/entities/quarantined-files/GET/v1", tok, body={"ids": q_ids})
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,47 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
result = call("GET", "/real-time-response/entities/scripts/v2", tok)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,61 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
id_ = INPUTS.get("id", "")
filter_ = INPUTS.get("filter", "")
offset = INPUTS.get("offset", "0")
limit = INPUTS.get("limit", "50")
if id_:
u_ids = csv(id_)
else:
params = [("offset", offset), ("limit", limit), ("sort", "uid")]
if filter_:
params.append(("filter", filter_))
query_res = call("GET", "/user-management/queries/users/v1", tok, params=params)
u_ids = query_res.get("resources", [])
result = call("POST", "/user-management/entities/users/GET/v1", tok, body={"ids": u_ids})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,60 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
filter_ = INPUTS.get("filter", "")
offset = INPUTS.get("offset", "0")
limit = INPUTS.get("limit", "50")
sort = INPUTS.get("sort", "")
params = []
if filter_:
params.append(("filter", filter_))
if offset:
params.append(("offset", offset))
if limit:
params.append(("limit", limit))
if sort:
params.append(("sort", sort))
result = call("GET", "/workflows/combined/definitions/v1", tok, params=params or None)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
params = [("ids", x) for x in csv(ids)]
result = call("GET", "/workflows/entities/execution-results/v1", tok, params=params or None)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,60 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
filter_ = INPUTS.get("filter", "")
offset = INPUTS.get("offset", "0")
limit = INPUTS.get("limit", "50")
sort = INPUTS.get("sort", "")
params = []
if filter_:
params.append(("filter", filter_))
if offset:
params.append(("offset", offset))
if limit:
params.append(("limit", limit))
if sort:
params.append(("sort", sort))
result = call("GET", "/workflows/combined/executions/v1", tok, params=params or None)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,68 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
hosts = INPUTS.get("hosts", "")
host_groups = INPUTS.get("host_groups", "")
file_paths = INPUTS.get("file_paths", "")
scan_inclusions = INPUTS.get("scan_inclusions", "")
description = INPUTS.get("description", "")
quarantine = INPUTS.get("quarantine", "")
body = {}
if hosts:
body["hosts"] = csv(hosts)
if host_groups:
body["host_groups"] = csv(host_groups)
if file_paths:
body["file_paths"] = csv(file_paths)
if scan_inclusions:
body["scan_inclusions"] = csv(scan_inclusions)
if description:
body["description"] = description
if quarantine:
body["quarantine"] = (str(quarantine).lower() == "true")
result = call("POST", "/ods/entities/scans/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,77 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_groups = INPUTS.get("host_groups", "")
file_paths = INPUTS.get("file_paths", "")
scan_inclusions = INPUTS.get("scan_inclusions", "")
description = INPUTS.get("description", "")
schedule_start_timestamp = INPUTS.get("schedule_start_timestamp", "")
schedule_interval = INPUTS.get("schedule_interval", "")
interval_map = {
"never": 0,
"daily": 1,
"weekly": 7,
"every other week": 14,
"every four weeks": 28,
"monthly": 30,
}
body = {
"host_groups": csv(host_groups),
"schedule": {
"interval": interval_map.get(schedule_interval.lower(), 0),
"start_timestamp": schedule_start_timestamp,
},
}
if file_paths:
body["file_paths"] = csv(file_paths)
if scan_inclusions:
body["scan_inclusions"] = csv(scan_inclusions)
if description:
body["description"] = description
result = call("POST", "/ods/entities/scheduled-scans/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
result = call("DELETE", "/ods/entities/scheduled-scans/v1", tok, params=[("ids", x) for x in csv(ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
file_ids = INPUTS.get("file_ids", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
if file_ids:
result = call("GET", "/ods/entities/malicious-files/v1", tok, params=[("ids", x) for x in csv(file_ids)])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
query_res = call("GET", "/ods/queries/malicious-files/v1", tok, params=params or None)
resources = query_res.get("resources", [])
if resources:
result = call("GET", "/ods/entities/malicious-files/v1", tok, params=[("ids", x) for x in resources])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
if ids:
result = call("GET", "/ods/entities/scans/v1", tok, params=[("ids", x) for x in csv(ids)])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
query_res = call("GET", "/ods/queries/scans/v1", tok, params=params or None)
resources = query_res.get("resources", [])
if resources:
result = call("GET", "/ods/entities/scans/v1", tok, params=[("ids", x) for x in resources])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
if ids:
result = call("GET", "/ods/entities/scan-hosts/v1", tok, params=[("ids", x) for x in csv(ids)])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
query_res = call("GET", "/ods/queries/scan-hosts/v1", tok, params=params or None)
resources = query_res.get("resources", [])
if resources:
result = call("GET", "/ods/entities/scan-hosts/v1", tok, params=[("ids", x) for x in resources])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,67 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
if ids:
result = call("GET", "/ods/entities/scheduled-scans/v1", tok, params=[("ids", x) for x in csv(ids)])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
query_res = call("GET", "/ods/queries/scheduled-scans/v1", tok, params=params or None)
resources = query_res.get("resources", [])
if resources:
result = call("GET", "/ods/entities/scheduled-scans/v1", tok, params=[("ids", x) for x in resources])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,48 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
result = call("GET", "/processes/entities/processes/v1", tok, params=[("ids", x) for x in csv(ids)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,50 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
type_ = INPUTS.get("type", "")
value = INPUTS.get("value", "")
device_id = INPUTS.get("device_id", "")
result = call("GET", "/indicators/queries/processes/v1", tok, params=[("type", type_), ("value", value), ("device_id", device_id)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,49 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_id = INPUTS.get("host_id", "")
result = call("POST", "/real-time-response/entities/refresh-session/v1", tok,
body={"device_id": host_id})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,58 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_group_id = INPUTS.get("host_group_id", "")
host_ids = INPUTS.get("host_ids", "")
result = call(
"POST",
"/devices/entities/host-group-actions/v1",
tok,
params=[("action_name", "remove-hosts")],
body={
"action_parameters": [{"name": "filter", "value": "(device_id:" + str(csv(host_ids)) + ")"}],
"ids": [host_group_id],
},
)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,59 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
id_ = INPUTS.get("id", "")
fields = {}
if INPUTS.get("status"):
fields["status"] = INPUTS.get("status")
if INPUTS.get("name"):
fields["name"] = INPUTS.get("name")
if INPUTS.get("description"):
fields["description"] = INPUTS.get("description")
if INPUTS.get("assigned_to_uuid"):
fields["assigned_to_user_uuid"] = INPUTS.get("assigned_to_uuid")
if INPUTS.get("severity"):
fields["severity"] = int(INPUTS.get("severity"))
result = call("PATCH", "/cases/entities/cases/v2", tok, body={"id": id_, "fields": fields})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,72 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
update_status = INPUTS.get("update_status", "")
assign_to_uuid = INPUTS.get("assign_to_uuid", "")
append_comment = INPUTS.get("append_comment", "")
add_tag = INPUTS.get("add_tag", "")
remove_tag = INPUTS.get("remove_tag", "")
unassign = INPUTS.get("unassign", "")
show_in_ui = INPUTS.get("show_in_ui", "")
action_parameters = []
for name, value in [
("update_status", update_status),
("assign_to_uuid", assign_to_uuid),
("append_comment", append_comment),
("add_tag", add_tag),
("remove_tag", remove_tag),
("unassign", unassign),
("show_in_ui", show_in_ui),
]:
if value:
action_parameters.append({"name": name, "value": value})
result = call("PATCH", "/alerts/entities/alerts/v3", tok, body={
"action_parameters": action_parameters,
"composite_ids": csv(ids),
})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,72 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
update_status = INPUTS.get("update_status", "")
assign_to_uuid = INPUTS.get("assign_to_uuid", "")
append_comment = INPUTS.get("append_comment", "")
add_tag = INPUTS.get("add_tag", "")
remove_tag = INPUTS.get("remove_tag", "")
unassign = INPUTS.get("unassign", "")
show_in_ui = INPUTS.get("show_in_ui", "")
action_parameters = []
for name, value in [
("update_status", update_status),
("assign_to_uuid", assign_to_uuid),
("append_comment", append_comment),
("add_tag", add_tag),
("remove_tag", remove_tag),
("unassign", unassign),
("show_in_ui", show_in_ui),
]:
if value:
action_parameters.append({"name": name, "value": value})
result = call("PATCH", "/alerts/entities/alerts/v3", tok, body={
"action_parameters": action_parameters,
"composite_ids": csv(ids),
})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,57 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_id = INPUTS.get("host_id", "")
qoff = str(INPUTS.get("queue_offline", "false")).lower() == "true"
timeout = INPUTS.get("timeout", "30")
init = call("POST", "/real-time-response/combined/batch-init-session/v1", tok,
body={"host_ids": [host_id], "queue_offline": qoff})
batch_id = init.get("batch_id")
result = call("POST", "/real-time-response/combined/batch-active-responder-command/v1", tok,
params=[("timeout", timeout)],
body={"base_command": "netstat", "batch_id": batch_id, "command_string": "netstat"})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,59 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_ids = INPUTS.get("host_ids", "")
qoff = str(INPUTS.get("queue_offline", "false")).lower() == "true"
timeout = INPUTS.get("timeout", "30")
init = call("POST", "/real-time-response/combined/batch-init-session/v1", tok,
body={"host_ids": csv(host_ids), "queue_offline": qoff})
batch_id = init.get("batch_id")
command_string = "runscript -Raw=" + chr(96) * 3 + "schtasks /query /fo LIST /v" + chr(96) * 3
result = call("POST", "/real-time-response/combined/batch-admin-command/v1", tok,
params=[("timeout", timeout)],
body={"base_command": "runscript", "batch_id": batch_id, "command_string": command_string})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,64 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_ids = INPUTS.get("host_ids", "")
file_path = INPUTS.get("file_path", "")
os_type = INPUTS.get("os", "Windows")
qoff = str(INPUTS.get("queue_offline", "false")).lower() == "true"
timeout = INPUTS.get("timeout", "30")
init = call("POST", "/real-time-response/combined/batch-init-session/v1", tok,
body={"host_ids": csv(host_ids), "queue_offline": qoff})
batch_id = init.get("batch_id")
if os_type == "Windows":
full = "rm '" + file_path + "' --force"
else:
full = "rm '" + file_path + "' -r -d"
result = call("POST", "/real-time-response/combined/batch-active-responder-command/v1", tok,
params=[("timeout", timeout)],
body={"base_command": "rm", "batch_id": batch_id, "command_string": full})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,76 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
types = INPUTS.get("types", "")
values = INPUTS.get("values", "")
sources = INPUTS.get("sources", "")
expiration = INPUTS.get("expiration", "")
limit = INPUTS.get("limit", "50")
sort = INPUTS.get("sort", "")
offset = INPUTS.get("offset", "")
filter_parts = []
if types:
filter_parts.append("type:" + types)
if values:
filter_parts.append("value:" + values)
if sources:
filter_parts.append("source:" + sources)
if expiration:
filter_parts.append("expiration:\"" + expiration + "\"")
filt = "+".join(filter_parts)
params = []
if filt:
params.append(("filter", filt))
if sort:
params.append(("sort", sort))
if offset:
params.append(("offset", offset))
if limit:
params.append(("limit", limit))
result = call("GET", "/iocs/combined/indicator/v1", tok, params=params if params else None)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,77 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
name = INPUTS.get("name", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
if ids:
ex_ids = csv(ids)
elif name:
params = [("filter", "name:~'" + name + "'")]
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
resp = call("GET", "/policy/queries/ioa-exclusions/v1", tok, params=params)
ex_ids = resp.get("resources", [])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
resp = call("GET", "/policy/queries/ioa-exclusions/v1", tok, params=params if params else None)
ex_ids = resp.get("resources", [])
if ex_ids:
result = call("GET", "/policy/entities/ioa-exclusions/v1", tok, params=[("ids", x) for x in ex_ids])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,82 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
value = INPUTS.get("value", "")
filter_ = INPUTS.get("filter", "")
limit = INPUTS.get("limit", "")
offset = INPUTS.get("offset", "")
sort = INPUTS.get("sort", "")
if ids:
ex_ids = csv(ids)
elif value:
params = [("filter", "value:'" + value + "'")]
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
if sort:
params.append(("sort", sort))
resp = call("GET", "/policy/queries/ml-exclusions/v1", tok, params=params)
ex_ids = resp.get("resources", [])
else:
params = []
if filter_:
params.append(("filter", filter_))
if limit:
params.append(("limit", limit))
if offset:
params.append(("offset", offset))
if sort:
params.append(("sort", sort))
resp = call("GET", "/policy/queries/ml-exclusions/v1", tok, params=params if params else None)
ex_ids = resp.get("resources", [])
if ex_ids:
result = call("GET", "/policy/entities/ml-exclusions/v1", tok, params=[("ids", x) for x in ex_ids])
else:
result = {"resources": []}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,50 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
cve_ids = INPUTS.get("cve_ids", "")
limit = INPUTS.get("limit", "50")
filt = "cve.id:['" + "','".join(csv(cve_ids)) + "']"
result = call("GET", "/spotlight/combined/vulnerabilities/v1", tok, params=[("filter", filt), ("facet", "host_info"), ("limit", limit)])
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,74 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ioc_id = INPUTS.get("ioc_id", "")
ind = {"id": ioc_id}
action = INPUTS.get("action", "")
if action:
ind["action"] = action
platforms = INPUTS.get("platforms", "")
if platforms:
ind["platforms"] = csv(platforms)
severity = INPUTS.get("severity", "")
if severity:
ind["severity"] = severity
source = INPUTS.get("source", "")
if source:
ind["source"] = source
description = INPUTS.get("description", "")
if description:
ind["description"] = description
expiration = INPUTS.get("expiration", "")
if expiration:
ind["expiration"] = expiration
result = call("PATCH", "/iocs/entities/indicators/v1", tok, body={"indicators": [ind]})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,58 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
host_group_id = INPUTS.get("host_group_id", "")
name = INPUTS.get("name", "")
description = INPUTS.get("description", "")
assignment_rule = INPUTS.get("assignment_rule", "")
res = {"id": host_group_id}
if name:
res["name"] = name
if description:
res["description"] = description
if assignment_rule:
res["assignment_rule"] = assignment_rule
result = call("PATCH", "/devices/entities/host-groups/v1", tok, body={"resources": [res]})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,77 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
body = {"id": INPUTS.get("id", "")}
exclusion_name = INPUTS.get("exclusion_name", "")
pattern_id = INPUTS.get("pattern_id", "")
pattern_name = INPUTS.get("pattern_name", "")
cl_regex = INPUTS.get("cl_regex", "")
ifn_regex = INPUTS.get("ifn_regex", "")
comment = INPUTS.get("comment", "")
description = INPUTS.get("description", "")
groups = INPUTS.get("groups", "")
detection_json = INPUTS.get("detection_json", "")
if exclusion_name:
body["name"] = exclusion_name
if pattern_id:
body["pattern_id"] = pattern_id
if pattern_name:
body["pattern_name"] = pattern_name
if cl_regex:
body["cl_regex"] = cl_regex
if ifn_regex:
body["ifn_regex"] = ifn_regex
if comment:
body["comment"] = comment
if description:
body["description"] = description
if groups:
body["groups"] = csv(groups)
if detection_json:
body["detection_json"] = detection_json
result = call("PATCH", "/policy/entities/ioa-exclusions/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,57 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
body = {"id": INPUTS.get("id", "")}
value = INPUTS.get("value", "")
comment = INPUTS.get("comment", "")
groups = INPUTS.get("groups", "")
if value:
body["value"] = value
if comment:
body["comment"] = comment
if groups:
body["groups"] = csv(groups)
result = call("PATCH", "/policy/entities/ml-exclusions/v1", tok, body=body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,76 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
name = INPUTS.get("name", "")
permission_type = INPUTS.get("permission_type", "private")
content = INPUTS.get("content", "")
boundary = "----RiposteBoundary7a3f91e2"
body_parts = []
for field_name, field_value in [("name", name), ("permission_type", permission_type), ("content", content)]:
body_parts.append(
"--" + boundary + "\r\n"
"Content-Disposition: form-data; name=\"" + field_name + "\"\r\n\r\n"
+ field_value + "\r\n"
)
body_parts.append("--" + boundary + "--\r\n")
body_bytes = "".join(body_parts).encode("utf-8")
headers = {
"Authorization": "Bearer " + tok,
"Accept": "application/json",
"Content-Type": "multipart/form-data; boundary=" + boundary,
}
req = urllib.request.Request(
BASE + "/real-time-response/entities/scripts/v1",
data=body_bytes,
headers=headers,
method="POST",
)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
result = json.loads(raw) if raw else {}
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,61 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
definition_id = INPUTS.get("definition_id", "")
name = INPUTS.get("name", "")
key = INPUTS.get("key", "")
source_event_url = INPUTS.get("source_event_url", "")
execution_cid = INPUTS.get("execution_cid", "")
params = [("definition_id", x) for x in csv(definition_id)]
if name:
params.append(("name", name))
params += [("execution_cid", x) for x in csv(execution_cid)]
if key:
params.append(("key", key))
if source_event_url:
params.append(("source_event_url", source_event_url))
json_body = json.loads(INPUTS.get("body") or "{}")
result = call("POST", "/workflows/entities/execute/v1", tok, params=params or None, body=json_body)
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)
@@ -0,0 +1,50 @@
import json, os, sys, urllib.request, urllib.parse, urllib.error
SECRETS = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}"))
INPUTS = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}"))
BASE = SECRETS.get("base_url", "https://api.crowdstrike.com").rstrip("/")
def token():
data = urllib.parse.urlencode({"client_id": SECRETS.get("client_id", ""), "client_secret": SECRETS.get("client_secret", "")}).encode()
req = urllib.request.Request(BASE + "/oauth2/token", data=data, headers={"Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read()).get("access_token", "")
def call(method, path, tok, params=None, body=None):
url = BASE + path
if params:
# params is a list of (key, value) tuples to allow repeated keys (e.g. ids)
url += "?" + urllib.parse.urlencode(params)
data = json.dumps(body).encode() if body is not None else None
headers = {"Authorization": "Bearer " + tok, "Accept": "application/json"}
if data is not None:
headers["Content-Type"] = "application/json"
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=90) as r:
raw = r.read()
return json.loads(raw) if raw else {}
def csv(v):
return [x.strip() for x in str(v or "").split(",") if x.strip()]
def main():
tok = token()
ids = INPUTS.get("ids", "")
action_name = INPUTS.get("action_name", "")
params = [("action_name", action_name)]
result = call("POST", "/workflows/entities/execution-actions/v1", tok, params=params, body={"ids": csv(ids)})
print(json.dumps(result))
try:
main()
except urllib.error.HTTPError as e:
print(json.dumps({"error": "HTTP " + str(e.code), "detail": e.read().decode("utf-8", "replace")}))
sys.exit(1)
except Exception as e:
print(json.dumps({"error": str(e)}))
sys.exit(1)