Files
2026-10-23 22:37:05 +02:00

193 lines
8.0 KiB
Markdown

# Running docker-vuln-scan in Komodo
Two ready-to-apply Resource Sync definitions are provided. Use **one** of them,
not both (they declare the same resource names):
| File | Use when |
| --- | --- |
| [`vuln-scan.toml`](vuln-scan.toml) | Komodo should clone this project from git and build the scanner itself. |
| [`vuln-scan-files-on-host.toml`](vuln-scan-files-on-host.toml) | You copy this project to the Komodo server and want Komodo to use those files. |
Both create:
- a **Stack** named `vuln-scan` on the selected Komodo Server, and
- a **Procedure** named `vuln-scan` that redeploys the stack every night,
which rebuilds the scanner image and runs one scan.
Alerts for HIGH/CRITICAL findings are sent **by the scanner directly through
Apprise**. You do not need a Komodo Alerter for that part.
## Before you start
- Komodo 2.x with a **Server** resource (Periphery) on the Docker host whose
images you want to scan.
- The project available to Komodo (git repo, or copied to the host).
- A reachable Apprise target (Discord, Slack, email, Telegram, ...).
### 1. Create the APPRISE_URLS variable
In Komodo: **Variables → New Variable**
| Field | Value |
| --- | --- |
| Name | `APPRISE_URLS` |
| Value | e.g. `discord://webhook_id/webhook_token` |
| Secret | **on** |
For several targets, separate them with a space:
```text
mailto://user:app-password@gmail.com tgram://bot_token/chat_id
```
The stack reads this variable through an `[[APPRISE_URLS]]` interpolation in its
`environment`, so do this before applying the sync.
> If you prefer to keep everything in the TOML file, add a `[[variable]]` block
> with `name = "APPRISE_URLS"`, `value = "..."` and `is_secret = true`. The
> value will then live in your sync git repo, so only do this in a private repo.
### 2. Apply the resources
#### Option A - git repo mode (recommended)
1. Push this project to a git repository Komodo can reach.
2. Edit `komodo/vuln-scan.toml`:
- `server = "server-prod"` → your Komodo Server name.
- `repo = "your-org/docker-vuln-scan"` → your repository.
- `IMAGES = ...` → the images you want to scan.
3. In Komodo: **Syncs → New Resource Sync → Git Repo**, then set:
- the repository and branch,
- `resource_path = ["komodo/vuln-scan.toml"]`,
- a git account if the repo is private.
4. Refresh the sync and review/apply the pending changes.
5. Open **Procedures → vuln-scan → Run** to start the first scan now.
#### Option B - files on the host
Komodo resolves files-on-host paths under the Periphery root directory
(default `/etc/komodo`, mounted at the same path in the standard Komodo compose
setup). The stack path is `/etc/komodo/stacks/<stack-name>`.
1. Copy the project to the Docker host:
```bash
sudo mkdir -p /etc/komodo/stacks/vuln-scan
sudo cp -r docker-vuln-scan/. /etc/komodo/stacks/vuln-scan/
```
(If you changed `PERIPHERY_ROOT_DIRECTORY`, use that path instead.)
2. Edit `komodo/vuln-scan-files-on-host.toml` (`server`, `IMAGES`).
3. Apply the file. It still needs to be readable by **Core**, which does not
mount `/etc/komodo` by default. Either keep the TOML in a git-based Resource
Sync, or create the Stack and Procedure in the UI using the values from the
file.
4. Run **Procedures → vuln-scan → Run**.
## What a run does
```
Procedure (cron) -> DeployStack -> docker compose build -> docker compose up -d
|
v
scanner container runs and exits
|
+---------------+---------------+
v v
Apprise alert (HIGH/CRITICAL) JSON report on disk
```
- `run_build = true` rebuilds the scanner image on the Komodo server. Layers
are cached, so only changes to `scan.py`/`Dockerfile` rebuild.
- `auto_pull = false` is required: the image is built locally and must not be
pulled from a registry.
- `ignore_services = ["vulnscan"]` tells Komodo that the exited one-shot
container is expected in status checks. Because this stack contains only that
one service, Komodo may still show the stack as stopped/down between runs.
That is normal for a scheduled one-shot job.
- `send_alerts = false` avoids daily status noise. Findings are reported by
Apprise instead.
`DeployStack` returns once `docker compose up -d` has started the container; it
does not wait for the scan to finish. The Apprise notification is the result
signal. The container exit code (`FAIL_ON`) is visible in the stack logs.
## Where the results are
On the scan server:
```
/etc/komodo/stacks/vuln-scan/reports/<image>.json
```
If your Periphery runs with a different root or the stack uses a `run_directory`,
adjust the path accordingly. The Compose volume is `./reports:/reports` relative
to the stack directory.
Logs:
- Komodo UI: **Stacks → vuln-scan → Logs**
- Shell: `docker compose -p vuln-scan logs vulnscan`
## Customizing
Edit the stack's `environment` (in the TOML or in Komodo) and re-apply the sync:
| Setting | Meaning |
| --- | --- |
| `IMAGES` | Space separated images to scan. Leave empty to scan the images used by running containers. |
| `DOCKER_SOCK` | Host path of the Docker socket (e.g. `/run/user/1000/docker.sock` for rootless Docker). |
| `INCLUDE_SELF` | `true` to also scan the scanner's own image when auto-discovering. |
| `APPRISE_URLS` | Notification target(s); usually kept in the secret variable. |
| `NOTIFY_MIN_SEVERITY` | Lowest severity that sends an alert (default `HIGH`). |
| `FAIL_ON` | Lowest severity that makes the container exit `1` (default `HIGH`). |
| `IGNORE_UNFIXED` | `true` to ignore findings without a fix. |
| `TRIVY_VEX` | VEX sources: `repo`, `oci`, `sbom-ref`, or local file paths (space separated). |
| `MAX_FINDINGS_IN_BODY` | Findings listed per notification. |
Schedule fields are on the Procedure:
```toml
[procedure.config]
schedule_format = "Cron"
schedule = "0 0 3 * * ?" # seconds minute hour day month weekday
schedule_timezone = "UTC"
```
To scan every image on the server instead of just the images in use, write the
list on the host and mount it:
```bash
docker image ls --format '{{.Repository}}:{{.Tag}}' \
| grep -v '<none>' > /etc/komodo/stacks/vuln-scan/images.txt
```
Then add `- ./images.txt:/images.txt:ro` to the `vulnscan` service volumes and
set `IMAGES_FILE = /images.txt` in the stack environment.
Private registries: add `TRIVY_USERNAME`, `TRIVY_PASSWORD` and optionally
`TRIVY_INSECURE` to the stack environment. The Compose file already passes
them through to the container.
VEX: set `TRIVY_VEX = repo`, `oci` or a combination in the stack environment.
For local files, add `- ./vex:/vex:ro` to the `vulnscan` service volumes in
`docker-compose.yml` and use a path such as `TRIVY_VEX = /vex/app.json`.
## Troubleshooting
| Symptom | Fix |
| --- | --- |
| Unresolved `[[APPRISE_URLS]]` / notification errors | Create the `APPRISE_URLS` variable (step 1) and re-apply. |
| `docker-vuln-scan:latest` pull error | Keep `auto_pull = false`; the stack builds the image locally. |
| Stack shows stopped/down between scans | Expected: the scanner is a one-shot container. Status alerts are disabled. |
| No findings at all | Check the image reference is correct; Trivy pulls registry images, and the Docker socket covers local-only images. |
| "No images configured ... nothing to scan" | The scanner cannot reach the Docker socket. With rootless Docker set `DOCKER_SOCK=/run/user/<uid>/docker.sock`, or set `IMAGES` explicitly. |
| Procedure success but no alert | Success only means the container started. Check stack logs and the Apprise target. |
| Need Komodo to fail on findings | Not covered by `DeployStack`; use `FAIL_ON` in CI or trigger the scanner from a Komodo Action that runs `docker run --rm` and inspects the exit code. |
## Security note
The scanner mounts `/var/run/docker.sock` and runs as root inside the container.
That is effectively root on the scan host, so only deploy it to servers and
Komodo users you trust.