GetLatest icon
OutputValues icon
Switch icon
Log icon
Create icon
SlackIncomingWebhook icon
Schedule icon

DigitalOcean Security Scan Critical Finding Compliance Gate

Audit DigitalOcean's latest CSPM security scan, alert Slack or auto re-scan on critical findings, and log the result for cloud security teams.

Categories
Infrastructure

DigitalOcean's built-in CSPM scanner finds misconfigurations like an exposed Droplet port or a publicly readable Spaces bucket, but it only ever shows the latest result inside the console; nothing pages a team when a new critical finding appears, and nothing confirms a fix actually cleared it until someone goes looking again. This blueprint reads the latest scan on a schedule, reports exactly which critical findings are open right now, and can kick off an immediate re-scan once you have explicitly said this flow is allowed to, so a fix gets verified without waiting for the next scheduled scan.

This blueprint was created by Mohit Jeswani.

How it works

  1. get_latest_scan (io.kestra.plugin.digitalocean.security.scan.GetLatest) reads the account's most recent CSPM scan and its findings. Read-only; nothing is scanned or changed here. allowFailure: true covers an API or auth error without failing the flow outright.
  2. evaluate (io.kestra.plugin.core.output.OutputValues) counts and lists the CRITICAL-severity findings with a jq filter, then classifies the result as COMPLIANT, NOT_CONFIGURED, CRITICAL_AUTO_RESCAN, CRITICAL_NEEDS_HUMAN, or PROBE_FAILED, folding confirm_rescan into the critical-findings classification itself.
  3. route (io.kestra.plugin.core.flow.Switch):
    • COMPLIANT: logs that the latest scan has no critical findings.
    • CRITICAL_AUTO_RESCAN: runs io.kestra.plugin.digitalocean.security.scan.Create (the safe remediation, since starting a scan changes no resources, it only asks DigitalOcean to re-evaluate), then posts a Slack notice.
    • CRITICAL_NEEDS_HUMAN / NOT_CONFIGURED / PROBE_FAILED: posts a Slack alert instead of re-scanning.
  4. summary logs the finding count and severity, closing the governance cycle.
  5. errors alerts Slack if the flow itself fails, for example a revoked API token.

What you get

  • A critical-findings count read from DigitalOcean's own scanner, not a third-party re-implementation of CSPM rules.
  • A re-scan that only ever asks DigitalOcean to re-evaluate the account, never changes a resource itself, and only runs once you have explicitly set confirm_rescan to allow it.
  • Explicit handling for the case DigitalOcean's own API documents but most integrations ignore: CSPM scanning not even being enabled on the account (NOT_CONFIGURED), which is itself a compliance gap worth paging on.

Who it's for

  • Cloud security and platform teams running workloads on DigitalOcean who want critical CSPM findings surfaced the day they appear, not discovered during a quarterly console review.
  • Teams evaluating the DigitalOcean plugin who want a worked example of the security.scan namespace used as a standing compliance gate, distinct from this repo's existing DigitalOcean blueprints, which track account balance, snapshot cost, and alert-policy configuration rather than security scan findings.

Why orchestrate this with Kestra

DigitalOcean's scanner finds the issues, but it has no escalation policy, no re-scan trigger after a fix, and no Slack integration of its own. Kestra keeps confirm_rescan as an explicit flow input, turns a raw findings list into a severity decision, and keeps a full execution history of every scan this flow has read and what it did in response.

Prerequisites

  • A DigitalOcean account with a personal access token that can read (and, for the re-scan path, start) security scans.
  • CSPM scanning enabled on the account, with at least one real scan run to confirm the compliant path; a finding can be left as-is or synthetically introduced to confirm the critical path.
  • A Slack incoming webhook URL.

DigitalOcean is a hosted cloud platform with no official standalone Docker image, so get_latest_scan cannot be exercised against a local container; validate against a real DigitalOcean account (a free trial credit is available) first.

Secrets

  • DIGITALOCEAN_TOKEN: the DigitalOcean personal access token used by get_latest_scan and start_rescan. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_DIGITALOCEAN_TOKEN.
  • SLACK_WEBHOOK_URL: used by all four Slack alert cases and the errors block. In Kestra OSS, provide it as the base64-encoded environment variable SECRET_SLACK_WEBHOOK_URL.

Inputs

Input Default Purpose
confirm_rescan false Authorizes this flow to start a fresh scan itself on critical findings

Outputs

  • {{ outputs.get_latest_scan.id }} / .status / .findings: the latest scan's ID, status (IN_PROGRESS, COMPLETED, FAILED, CSPM_NOT_ENABLED, or SCAN_NOT_RUN), and findings (rule_uuid, name, severity, details, mitigation_steps, affected_resources_count), as DigitalOcean reports them.
  • {{ outputs.evaluate.values.critical_count }} / .critical_summary: how many findings are CRITICAL and a semicolon-joined name (N resource(s)) summary of each.
  • {{ outputs.evaluate.values.severity }}: COMPLIANT, NOT_CONFIGURED, CRITICAL_AUTO_RESCAN, CRITICAL_NEEDS_HUMAN, or PROBE_FAILED.

Pitfalls

  • GetLatest returns at most one page of findings (perPage, default and max 200); an account with more than 200 open findings needs page chained across repeated calls to see them all. This blueprint reads only page 1.
  • status can be CSPM_NOT_ENABLED or SCAN_NOT_RUN even when the API call itself succeeds; verified directly against the task's own Javadoc and ScanOutput.java, since treating either as a parsing failure would silently hide a real "no compliance signal exists" condition instead of alerting on it.
  • confirm_rescan starts a new scan on every run that finds a critical finding, not once per finding; a scheduled run that keeps finding the same unresolved critical finding will re-scan every time it fires, which is harmless but not free of DigitalOcean API quota.

Quick start

  1. Add the DIGITALOCEAN_TOKEN and SLACK_WEBHOOK_URL secrets.
  2. Confirm CSPM scanning is enabled on the account and at least one scan has completed.
  3. Run the flow manually and confirm summary logs a finding count.
  4. With a known critical finding present, run with confirm_rescan: false and confirm alert_critical fires.
  5. Run again with confirm_rescan: true and confirm start_rescan starts a new scan and alert_auto_rescanned fires with its ID.
  6. Enable the daily trigger once the inputs reflect your real policy.

How to extend

  • Chain io.kestra.plugin.digitalocean.security.scan.ListAffectedResources for the highest-severity finding to name the exact Droplets or resources affected in the Slack alert, not just the finding's rule name.
  • Add a second threshold on HIGH-severity findings for a quieter, non-paging Slack channel, separate from the CRITICAL path.
  • Page through every findings page with page and a Loop once an account regularly carries more than 200 open findings.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.