New to Kestra?
Use blueprints to kickstart your first workflows.
Fetch a Netskope Security Cloud alert type, alert Slack when the count reaches a threshold, and log the result for SOC teams.
Netskope's own console surfaces alerts as they happen, but a SOC still needs someone to open the dashboard and notice a spike in compromised-credentials or DLP alerts. This blueprint polls a single Netskope alert type on a schedule, counts what came back, and pages Slack the moment that count crosses a threshold you set, rather than relying on the console being open.
This blueprint was created by Mohit Jeswani.
get_alerts (io.kestra.plugin.netskope.events.GetAlerts) polls the Netskope v2 Data
Export alerts endpoint for alert_type, optionally narrowed by an NRSQL query. Read-only;
no alert is modified. allowFailure: true covers an API or auth error without failing the
flow outright.evaluate (io.kestra.plugin.core.output.OutputValues) compares alertCount against
max_alert_count. A failed fetch is also CRITICAL.route (io.kestra.plugin.core.flow.If):summary logs the count and severity, closing the governance cycle.errors alerts Slack if the flow itself fails, for example an expired API token.outputs.get_alerts.uri), already in Kestra's
internal storage, for whoever triages it next.compromised-credentials, another for dlp, each with its own threshold.events.GetAlerts used as
a volume-based governance check.Netskope raises the alert; it does not decide a cadence, compare the volume to a threshold
you control, or notify a specific Slack channel. Kestra keeps max_alert_count as a flow
input, turns a poll into a Slack page naming the exact count, and keeps a full execution
history of every check.
alert_type in the tenant, to confirm the count is nonzero when
expected.This flow calls the Netskope REST API directly over HTTPS; there is no official local
Netskope emulator, so get_alerts cannot be exercised against a local Docker container.
Validate against a real tenant, ideally a non-production one.
NETSKOPE_V2_TOKEN: the Netskope v2 API token used by get_alerts, sent as the
Netskope-Api-Token header. In Kestra OSS, provide it as the base64-encoded environment
variable SECRET_NETSKOPE_V2_TOKEN.SLACK_WEBHOOK_URL: used by alert and the errors block. In Kestra OSS, provide it as
the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.| Input | Type | Default | Allowed values |
|---|---|---|---|
netskope_tenant |
STRING | <your-tenant> |
Netskope tenant subdomain |
alert_type |
STRING | compromised-credentials |
Valid Netskope alert type (e.g., malware, dlp, policy, compromised-credentials) |
query |
STRING | "" |
Optional NRSQL filter expression |
max_alert_count |
INT | 1 |
Any non-negative integer |
{{ outputs.get_alerts.alertCount }}: number of alerts returned in the response.{{ outputs.get_alerts.uri }}: internal storage URI of the full raw alert response JSON file.{{ outputs.evaluate.values.alert_count }}: evaluated alert count (-1 on probe failure).{{ outputs.evaluate.values.severity }}: compliance classification (OK, ALERT_THRESHOLD_BREACH, or CRITICAL).alertType has no fixed enum enforced by this task; a typo'd alert type does not error, it
silently returns zero alerts, which reads as compliant. Confirm the exact type string
against your tenant's own alert taxonomy first.GetAlerts does not expose per-alert fields (ID, severity, source) as typed outputs, only
the total count and the raw stored file; reading individual alert details requires parsing
outputs.get_alerts.uri yourself downstream.NETSKOPE_V2_TOKEN and SLACK_WEBHOOK_URL secrets.netskope_tenant and alert_type to a real tenant and type you expect activity on.summary logs a count.max_alert_count to 0 to confirm alert fires even with a small, real alert count.hourly trigger once the threshold reflects your actual alerting tolerance.outputs.get_alerts.uri with read() and fromJson() in a downstream task to extract
individual alert IDs, then loop io.kestra.plugin.netskope.remediation.UpdateAlert to
acknowledge each one, once you have confirmed the exact ID field name your tenant's alert
payload uses.alert_type, each with its own
max_alert_count and Slack channel.query tier (for example a specific user or destination) that pages
a more senior on-call channel when it matches.