OutputValues icon
Switch icon
Log icon
Loop icon
If icon
Move icon
SlackIncomingWebhook icon
Trigger icon

NFS New File Extension Compliance Gate

Fire on new NFS file arrivals, alert Slack or auto-quarantine non-compliant files, and log the result for data platform teams.

Categories
Data

A shared NFS drop directory that many systems can write to eventually gets something that does not belong: an executable where only CSVs were expected, a stray temp file, a wrong export format from a misconfigured upstream job. Nothing about NFS itself enforces what kind of file a directory is supposed to receive; by the time a downstream job trips over it, the file could have been sitting there for hours. This blueprint watches a directory in real time, checks every new arrival against an approved extension pattern, and can quarantine the ones that fail once you have explicitly said this flow is allowed to.

This blueprint was created by Mohit Jeswani.

How it works

  1. watch_directory (io.kestra.plugin.fs.nfs.Trigger) polls the watched directory and fires with every newly created file's name, URI, and metadata in trigger.files.
  2. evaluate (io.kestra.plugin.core.output.OutputValues) counts and lists the files whose name does not match allowed_extensions_regex with a jq filter, and classifies the fire as ALL_COMPLIANT, NONCOMPLIANT_AUTO_QUARANTINE, or NONCOMPLIANT_NEEDS_HUMAN, folding confirm_quarantine into the non-compliant classification itself.
  3. route (io.kestra.plugin.core.flow.Switch):
    • ALL_COMPLIANT: logs that every new file matched the pattern.
    • NONCOMPLIANT_AUTO_QUARANTINE: ForEachs every file this fire delivered, moves only the non-compliant ones into quarantine_directory with io.kestra.plugin.fs.nfs.Move (the safe remediation, since moving a file within the same NFS mount deletes nothing), then posts a Slack notice.
    • NONCOMPLIANT_NEEDS_HUMAN: posts a Slack alert instead of quarantining.
  4. summary logs the non-compliant count and severity, closing the governance cycle.
  5. errors alerts Slack if the flow itself fails, for example an unmounted NFS path.

What you get

  • A file-type policy enforced the moment a file lands, not discovered when a downstream job chokes on it hours later.
  • A quarantine move that only ever relocates a file within the same NFS mount, deletes nothing, and only runs once you have explicitly set confirm_quarantine to allow it.
  • A Slack alert naming the exact non-compliant filenames, so whoever owns the directory can trace them back to the source system that wrote them.

Who it's for

  • Data platform and integration teams who run a shared NFS drop directory fed by multiple upstream systems and need a file-type policy enforced automatically.
  • Teams evaluating the fs plugin's NFS support who want a worked example of nfs.Trigger and nfs.Move used together as an event-driven compliance gate, distinct from this repo's existing NFS blueprint, which runs a nightly scheduled sweep deleting stale scratch files by age rather than reacting to a new arrival's file type in real time.

Why orchestrate this with Kestra

NFS has no concept of an allowed file-type policy and no way to react the moment a non-compliant file lands. Kestra keeps allowed_extensions_regex, quarantine_directory, and confirm_quarantine as flow inputs, turns a trigger's file batch into a policy decision, and keeps a full execution history of every arrival this flow has seen and what it did about it.

Prerequisites

  • An NFS share mounted on the Kestra worker, with a directory new files can be written into to test both the compliant and non-compliant paths.
  • A Slack incoming webhook URL.

A local NFS server can be run via an open-source Docker image such as itsthenetwork/nfs-server-alpine, mounted into the Kestra worker container, for a fully local end-to-end test, no managed service required.

Secrets

  • SLACK_WEBHOOK_URL: used by both 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
allowed_extensions_regex .*\\.(csv|json|parquet)$ Pattern a filename must fully match to be compliant
quarantine_directory /mnt/nfs/quarantine Where non-compliant files are moved when authorized
confirm_quarantine false Authorizes this flow to quarantine non-compliant files itself

The watched directory is set directly on the watch_directory trigger's from, not as a flow input; see Pitfalls.

Outputs

  • {{ trigger.files }}: every new or updated file this fire detected (name, uri, size, isDirectory, isHidden, creationTime, lastModifiedTime, changeType), as nfs.Trigger reports them.
  • {{ outputs.evaluate.values.noncompliant_count }} / .noncompliant_names: how many files failed the pattern and their names, semicolon-joined.
  • {{ outputs.evaluate.values.severity }}: ALL_COMPLIANT, NONCOMPLIANT_AUTO_QUARANTINE, or NONCOMPLIANT_NEEDS_HUMAN.

Pitfalls

  • from, interval, on, recursive, and maxFiles are trigger-level configuration, not flow inputs; a polling trigger has no per-execution input overrides the way a Schedule trigger does, so watching a different directory means editing the trigger block directly.
  • nfs.Trigger caps a single fire at maxFiles (default 25); a directory that receives a larger burst than that in one poll interval has the excess files picked up on the next poll instead, not dropped.
  • nfs.Move's destination directory is created automatically if it does not exist, and an existing file at the destination path is overwritten; two different source files sharing a filename quarantined in the same run will collide, with the second overwriting the first.

Quick start

  1. Add the SLACK_WEBHOOK_URL secret.
  2. Run a local NFS server via Docker, mount it into the worker, and point watch_directory's from at a real incoming directory.
  3. Enable the trigger, write a compliant file (e.g. report.csv), and confirm log_all_compliant fires.
  4. Write a non-compliant file (e.g. malware.exe) with confirm_quarantine: false; confirm alert_noncompliant fires.
  5. Set confirm_quarantine: true, write another non-compliant file, and confirm move_to_quarantine relocates it and alert_auto_quarantined fires.

How to extend

  • Add a file-size ceiling alongside the extension check, quarantining oversized files even when their extension is otherwise approved.
  • Chain a checksum or antivirus scan on each non-compliant file before quarantining it, to distinguish a wrong-format mistake from something actively malicious.
  • Watch several directories by deploying one copy of this flow per watch_directory trigger configuration, one per drop zone your team owns.

Links

See How

New to Kestra?

Use blueprints to kickstart your first workflows.