GetAlerts icon
OutputValues icon
If icon
SlackIncomingWebhook icon
Log icon
Schedule icon

Netskope Security Alert Volume Sentinel

Fetch a Netskope Security Cloud alert type, alert Slack when the count reaches a threshold, and log the result for SOC teams.

Categories
CoreInfrastructure

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.

How it works

  1. 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.
  2. evaluate (io.kestra.plugin.core.output.OutputValues) compares alertCount against max_alert_count. A failed fetch is also CRITICAL.
  3. route (io.kestra.plugin.core.flow.If):
    • compliant: logs the count, below threshold.
    • alert: posts the count and the stored response's storage URI to Slack.
  4. summary logs the count and severity, closing the governance cycle.
  5. errors alerts Slack if the flow itself fails, for example an expired API token.

What you get

  • A Slack page the moment a specific alert type crosses a volume threshold, not a dashboard someone has to remember to check.
  • A link straight to the full alert payload (outputs.get_alerts.uri), already in Kestra's internal storage, for whoever triages it next.
  • A per-alert-type, per-query check you can run several of side by side, one for compromised-credentials, another for dlp, each with its own threshold.

Who it's for

  • SOC and security operations teams running Netskope Security Cloud who want one alert type's volume watched on a schedule, independent of the console.
  • Teams evaluating the Netskope plugin who want a worked example of events.GetAlerts used as a volume-based governance check.

Why orchestrate this with Kestra

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.

Prerequisites

  • A Netskope Security Cloud tenant with the v2 Data Export API enabled and a v2 API token.
  • At least one alert of alert_type in the tenant, to confirm the count is nonzero when expected.
  • A Slack incoming webhook URL.

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.

Secrets

  • 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.

Inputs

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

  • {{ 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).

Pitfalls

  • 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.
  • This task stores the full raw response on every run, including when there are zero alerts; size that into your retention expectations for Kestra's internal storage on a tight schedule.
  • 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.

Quick start

  1. Add the NETSKOPE_V2_TOKEN and SLACK_WEBHOOK_URL secrets.
  2. Set netskope_tenant and alert_type to a real tenant and type you expect activity on.
  3. Run the flow with the defaults and confirm summary logs a count.
  4. Lower max_alert_count to 0 to confirm alert fires even with a small, real alert count.
  5. Enable the hourly trigger once the threshold reflects your actual alerting tolerance.

How to extend

  • Read 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.
  • Run several copies of this flow side by side, one per alert_type, each with its own max_alert_count and Slack channel.
  • Add a second, narrower query tier (for example a specific user or destination) that pages a more senior on-call channel when it matches.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.